Liquid Barcodes Application Feed Interface JSON/REST

Introduction

The app-API allows Liquid Barcodes to distribute coupons and other content to your app and a host of additional functionality.

 

USER REGISTRATION

Before content can be distributed to the user’s app, the user must be registered. The API requires a unique and persistent ID to be created per user upon registration.

  • Registration with consent: creating a unique user profile can be handled entirely by Liquid Barcodes, in which case you will normally have to register consent as part of the registration process.
  • Register user - I handle consent myself: If you already have a registration service, the registration to Liquid Barcodes can be done in the background without involving the user.

These two registration processes are described in detail below.

 

CONTENT DISTRIBUTION

Liquid Barcodes will populate a record per user with information to display in the app. Liquid Barcodes will ensure that the data in the record at all times is correct, and will remove coupons when they expire, have been redeemed etc. This record is obtained through the API using GET /content function. The record contains one or several coupons, games or surveys that are distributed as content objects (see content model below for detailed description).

Content can be presented in one or multiple locations in the app, described in detail below as sections.

Liquid Barcodes will populate each users' record based on the campaigns that have been created in Liquid Barcodes dashboard. This process is handled in its entirety in Liquid Barcodes back end.

General principles

Background

This document describes the application interface to register a user, request the user’s coupons, loyalty cards, promotions, rewards, surveys and games. The document is organized in sections to describe functionality classes, and not every functionality class may be relevant for every mobile application. They are however included to detail the fully fledged functionality, but may not be present in the actual implementation for this particular purposes. The full functionality of the practical implementation has to be agreed with Liquid Barcodes before using the services provided.

Nomenclature

A user is an end customer that is using the application.

A coupon gives user right to a financial discount or rebate when purchasing a product. A coupon can take many forms, such as single use rebate coupons, loyalty cards, reward coupons, limited coupons etc. All these should be treated equally by the app.

HTML based content is some content that is displayed in the in-app web browser, for example games, surveys and weblink images. Common to all these content types is that user is presented with an image that works like a button to open the HTML content.

Shop offer: a content object that end users can buy. Purchasing these items will trigger issue of related content, eg. coupons or gift card balance top up.

Preferred API format and HTTP Headers

The preferred content type for the requests that are being sent to LIQUID is JSON. For every function call the following parameters are always
placed in the HTTP header:

  • X-Liquid-Timestamp – datetime in ISO-8601 format. e.g. 2014-03-06T13:11:04+03:00. Time should be in UTC
  • X-Liquid-Signature – signature calculated in the manner described above

Signature

The Application ID and the security details are available on request. This API relies on the use of SHA-2 256 hash signatures with all mandatory
parameters + a secret salt known only by Liquid Barcodes and the customer (you).

 

Let's say we have agreed upon the secret salt "wild-e-coupon". Then, the source for the checksum would be "abcd" + "1234" + "wild-e-coupon".
The correct checksum would be:

SHA-2 256("2014-03-07T11:07:21+01:00abcd1234wild-e-coupon")
= 800226d761b1bfe2248f68a353f73e720ab9322408dff29f50ed2dba223432e2

Each service specification below will detail how to build the source for the checksum, that is, which parameters and the order in which they should
be concatenated.

JSON

Example (pseudo) service call:

{
"DateTimeHeader": "2014-03-07T11:07:21+01:00"
"parameter_a": "abcd",
"parameter_b": "1234",
"signature": "1aaade12efceba0f9ddda4a94bce59a6"
}

 

Signature debugging tool

 

General Disclaimer

This document describes the interface to get the relevant content (coupons, games, survey etc.) for a unique user and application. In order to utilize this interface there must be a commercial agreement with Liquid Barcodes in place. In all circumstances the IPR of the interface resides with Liquid Barcodes. Liquid Barcodes reserves the right to change this interface at any moment. Any implementation that utilizes this interface is the sole responsibility of the implementer, and under no circumstances should the issuing of this document be construed to signify that Liquid Barcodes will participate with the implementation, testing, verification of the implementation, unless otherwise agreed.

User models

These models are used by various requests related to user registration and user management.

The User model

Contains all the user information about each user available to the app.

 

Parameter Description
UserId For new users the UserId will match the UserId from the request.
For returning users the UserId will be the UserId previously associated with the MSN.
Msn Users mobile number.
Name Optional: Name of user
Address Optional: Address of user
PostCode Optional: User's zip code
City Optional: User's city of residence
Email Optional: User's preferred e-mail
DateOfBirth Optional: User's date of birth in ISO-8601 format (yyyy-mm-dd).
Gender Optional: User's gender specified as M or F.
PreferredStores Optional: : List of user's preferred store(s) based on their interaction with the system. This is a JSON array of stores l
isted in most preferred store first. Must use the same StoreId as available in Stores section of this document. A store
can be present in both PreferredStores (set by the system) and SelectedPreferredStore (selected by the user)
SelectedPreferredStores Optional: List of user's selected preferred store(s). This is a JSON array of stores listed in most preferred store first.
Must use the same StoreId as available in Stores section of this document. A store can be present in both
PreferredStores (set by the system) and SelectedPreferredStore (selected by the user)
UserGroups Optional: Array of userGroups for this user
GroupId A unique identifier for this group
GroupDescription A human readable description to be displayed to the user
IsUserMember Only accepted values are 'True' or 'False', meaning that the user is part of the group or not part
of the group, respectively
UserConfigurable Takes one of the following values:
'NotConfigurable' - The user cannot toggle membership him/herself
'Configurable' - The user is allowed to change the group membership status him/herself
'CodeConfigurable' - The user is allowed to change the group membership status him/herself
but it requires an additional code to be entered by the user in the app
Additional values may be added in the future, and unrecognized values should default to
'NotConfigurable'
Culture Optional: Indicates the users culture / language. Must be one of the values from the /languages service. Values
follow RFC 4646.
Consents Array of consents (see Consent situation model) that is appllicable for this user to use this application. Any
Mandatory consents must be displayed and approved by the user before POST /user call. If using 'Deterministic
PIN' the consent handling is the responsibility of the calling party and this section will be empty.
UserMyPage Link to HTML page with advanced settings (including historic data for the user)

POST /initialize

This is the first service to be called for a uninitialized app instance. This function call is normally only done initially, or when the user has logged out. The service expects the following parameters in the body of the request:

 

REQUEST

Parameter Description
Third party UserID A unique identifier for the device that as far as possible is persistent when the user logs in after having a) logged out, b) deleted and re-installed the app, and c) done a factory reset (if possible). This identifier is used to prevent fraud by setting limitations on the number of times a user can use the same device with different MSNs.
Culture Optional: Indicates the users culture / language. Only values present in the /languages service are accepted. Values follow RFC 4646. This feature is only used if your app supports more than 1 language

 

The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) + DeviceId+ Your secret salt 

 

RESPONSE

The service replies with HTTP-200 status when the operation was successful, the body of the response will contain:

Parameter Description
UserId A randomly created user ID. The app should store this UserId for use with the following service calls.
Consents Array of consents (see Consent situation model) that is appllicable for this user to use this application. Any Mandatory consents must be displayed and approved by the user before POST /user call. If using 'Deterministic PIN' the consent handling is the responsibility of the calling party and this section will be empty.

POST /pin

Before a user can be registered he must order a PIN to his mobile number to confirm he is the owner of that mobile number. The users PIN must then be used as with the POST /user service to register a new user.

The service expects the following parameters in the body of the request:

 

REQUEST

Parameter
Description
UserId UserId, a unique ID for the given User that is assigned by LIQUID.
Msn Mobile number where the PIN will be sent. (Optional parameter if using Deterministic PIN mode)

 

The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) + UserID + MSN + Your secret salt

 

RESPONSE

The service replies with HTTP-200 status when the operation was successful, the body of the response will contain:

Parameter
Description
Pin Optional: The PIN code to use for the POST /user call. This is only relevant for a deterministic pin
Status
Value
Description
Message suggestion
SmsSent A new SMS has been sent Engangspassord er sendt til deg på SMS
PinOnItsWay SMS has not been sent; 3 SMS messages has already been sent to the user before Kunne ikke sende engangspassord til oppgitt nummer, prøv igjen litt senere
PinToUse The PIN code to use is included in this response. This is only relevant for a deterministic pin

POST /user

Registers a new user profile and returns the users UserId. In case of returning users that needed to re-register, their previously UserId will be returned. The mobile app must then replace it's UserId.

The service expects the following parameters in the body of the request:

 

Parameter Description
UserId UserId, a unique ID for the given User that is assigned by LIQUID.
Pin Users PIN code (see POST /pin).
Msn Optional: The MSN of the user (only allowed to set MSN when using deterministic PIN)
Name Optional: Name of user
Address Optional: Address of user
PostCode Optional: User's zip code
City Optional: User's city of residence
Emails Optional: List of user's preferred e-mails
DateOfBirth Optional: Users date of birth in ISO-8601 format (yyyy-mm-dd).
Gender Optional: User's gender specified as M or F.
SelectedPreferredStores Optional: List of the user's selected preferred store(s). This is a JSON array of stores listed in most preferred store first. Must use the same StoreId as available in Stores section of this document
Culture Optional: Indicates the users culture / language. Must be one of the values from the /languages service. Values follow RFC 4646.
ApprovedConsents A list of approved consent IDs.
RevokedConsents A list of revoked consent IDs. (Note: first we will revoke any sent consents and then only add any approved)

 

The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) + UserID + PIN + Your secret salt

 

 

RESPONSE

The service replies with HTTP-200 status when the operation was successful, the body of the response will be the current user model.

PUT /user

Updates a user's profile data.

The service expects the following parameters in the body of the request:

 

REQUEST

Parameter Description
UserId UserId, a unique ID for the given User that is assigned by LIQUID.
Msn Optional: The MSN of the user (only allowed to change MSN when using deterministic PIN)
Name Optional: Name of user
Address Optional: Address of user
PostCode Optional: User's zip code
City Optional: User's city of residence
Emails Optional: List of user's preferred e-mail
DateOfBirth Optional: Users date of birth in ISO-8601 format (yyyy-mm-dd).
Gender Optional: User's gender specified as M or F.
SelectedPreferredStores Optional: List of user's selected preferred store(s). This is a JSON array of stores listed in most preferred store first. Must use the same StoreId as available in Stores section of this document. A store can be present in both PreferredStores (set by the system) and SelectedPreferredStore (selected by the user)
UserGroups Optional: Array of userGroups that is applicable to this user
GroupId A single word tag for this group. Only tags that have been fetched through Get /User is accepted
IsUserMember Only accepted values are 'True' or 'False', meaning that the user is to join/is joined or is to quit/has quit the group in question
UserCode Provides a needed code to verify the change of status if UserConfigurable = 'CodeConfigurable'. Blank otherwise
Culture Optional: Indicates the users culture / language. Must be one of the values from the /languages service. Values follow RFC 4646.
ApprovedConsents A list of approved consent IDs. 
RevokedConsents A list of revoked consent IDs. (Note: first we will revoke any send consents and then only add an approved)

 

The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) + UserID + Your secret salt

 

RESPONSE

The service replies with HTTP-200 status when the operation was successful, the body of the response will be the current user model. A change of status on the UserGroup must be fetched through GET /user.

GET /languages

Lists the possible languages / cultures the user can select in this app.

 

REQUEST

The service has no arguments but the standard headers.

The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) + your secret salt.

 

RESPONSE

The response will be a dictionary with culture key and language name, for example:

 

Key
Value
de_DE German (Germany)
en_GB English (Great Britian)

 

This means de_DE and en_GB are the valid alternatives to send in the PUT /user service's Culture field.

POST /user

Call this service when you have registered a new user in your system. The service expects the following parameters in the body of the request:

 

Parameter Description
UserId A unique and persistent UserId created in your system.
Msn Optional: The MSN of the user (only allowed to set MSN when using deterministic PIN)
Name Optional: Name of user
Address Optional: Address of user
PostCode Optional: User's zip code
City Optional: User's city of residence
Emails Optional: List of user's preferred e-mails
DateOfBirth Optional: Users date of birth in ISO-8601 format (yyyy-mm-dd).
Gender Optional: User's gender specified as M or F.
SelectedPreferredStores Optional: List of the user's selected preferred store(s). This is a JSON array of stores listed in most preferred store first. Must use the same StoreId as available in Stores section of this document
Culture Optional: Indicates the users culture / language. Must be one of the values from the /languages service. Values follow RFC 4646.
ApprovedConsents A list of approved consent IDs.
RevokedConsents A list of revoked consent IDs. (Note: first we will revoke any sent consents and then only add any approved)

 

The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) + UserID + Your secret salt

 

 

RESPONSE

The service replies with HTTP-200 status when the operation was successful, the body of the response will be the current user model.

Manage and edit user

To update user information, use the PUT /user function. You can update all information about the user except the unique user identificator used to identify each user (usually phone number).

For GDPR compliance, in the User model Liquid Barcodes provides link to our generic My page. The link is dynamic and unique for each user. Make sure to link to this page in your app to fulfill all GDPR requirements.

 

User rights

The API provides basic account information and a link to advanced ‘My page’ solution. Make sure to link to this ‘My page’ solution to ensure full compliance with user rights under GDPR. Expect the ‘My page’ link to be unique and dynamic for each user.

 

Customer user groups

Customers can reveal their preferences by joining customer user groups. All available groups and the user's status are presented in GET /user. Groups can be free opt in, require code, or not editable. The presentation of the list of groups in the app should be dynamic to allow for future changes to the groups.

 

Select preferred store(s)

Use this flow to let users to select their preferred stores to get local offers and regional offers.

 

GET /user

Gets a user profile. Expects the following parameters in the URL query-string.

 

Parameter
Description
UserID UserId, a unique ID for the given User that is assigned by LIQUID.

 

The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) + UserID + Your secret salt

 

RESPONSE

The service replies with HTTP-200 status when the operation was successful, the body of the response will be the current user model.

PUT /user

 

See PUT /user under Register user with consent.

Content management

In most cases, the main content of the app is obtained through the GET /content request. It gives the app access to each users unique content record that can contain coupons, games and/or surveys.

Liquid Barcodes content is organized in a hierarchy, the app should follow this hierarchy and not tamper with the organization or order content is sent to the app:

  • Request: GET /content gives access to all users coupon, game and survey content, presented in the content model form.
  • Sections: The content is grouped into sections. Your app may have only one section or multiple sections. Each section should correspond to a designated are in the app where Liquid Barcodes content is displayed, eg. an 'Offers room'.
  • Content objects: within each section, there can be none, one or multiple content objects. These may be Coupon content or HTML content. The app must be able to handle these two, and only these two, content types. Present the content in the same order as they appear in the API.
  • Content model: the structure of each content object is described in the content model.

 

Some general content guidelines:

  • Add a refresh button to allow the user to update content. As a minimum, this should force a refresh of all content for this content object.
  • Update images based on HTML headers.
  • Make it possible to share coupons if the coupon is shareable (LB defines shareable or not)
  • Make sure to use the various information according to its intention (e.g. the parameter BackUrl should be placed on the backside of the coupon)
  • The app should not filter or alter the order of content obtained through content requets such as Get Content or Get ShopOffers requests

 

OFFLINE HANDLING

In order to improve the user experience, it is suggested to have a graceful offline caching. Cache data locally to ensure app functions even without internet connection. Do not delete cache on device if in offline mode or no response from server. The app should work without connection (albeit with limited functionality).

All image URLs that is returned contains the form https://www.domain.com/path/filename.extension?v=guid. Whenever an image changes the URL will also change (possibly the filename, but always the GUID). Thus an image change will result in a new and unique URL. Any device/app caching mechanisms used must miss and load the image for such new and unique URLs.

Sections

All coupon objects are structured in groups called sections.

When setting up a campaign the retailer will define which section the content should be assigned to. All content types can appear in all sections, provided that the app supports this.

Each section should be displayed in its entirety in one designated space in the app. One app may contain one or several such spaces, depending on your requirements, with one corresponding section per space. The number of Sections can be configured to your needs.

However the content in each section should be kept together in the order specified by the section.

Coupon content

Designated Type=Coupon in the Content model. Use coupon handling as fallback method to present any unknown content in the GET /content response.

Coupon content are typically coupons, loyalty cards or similar items where the purpose is to give the user a discount in store. Coupon objects consist of a series of elements that should be presented in this way:

The TopImageUrl will always be present, but any or all of the remaining parameters may be empty. The app should be robust and display the coupon regardless of which parameters are present. The app must handle images that are too small or too large (aspect ratio not optimal for current screen size).

HTML content

Designated Type=HTML in the Content model.

HTML content is content that requires the app to open in-app browser. There are two key elements:

  • an image that works like a button: When user clicks the image, open the unique content link. Designated TopImageUrl in the Content model.
  • content link: the URL that is to be opened in the in-app browser. Designated ContentUrl in the Content model.

Make sure to test the app with various types of HTML content before releasing to customers.

Content model

The content object is used in a several places and has two different states:

  • Activated, this means that the content has already been issued either by a user action or because the underlying campaign automatically issues the content to the user
  • Not yet activated, is currently not implemented

 

Parameter Description Activated content Not yet activated content (not implemented)
ScheduleId LIQUID Barcodes' internal Schedule identifier. Mandatory Mandatory
ContentId LIQUID Barcodes unique content identifier. Only available for unique content. Mandatory
TopImageUrl Optional: URL to the top image part of the content. Either TopImageUrl or ContentUrl has to be present  Optional Optional
TopText Optional: Top text for the coupon which can be 1-3 lines of text. The most common use of this parameter is the text "Valid to ...", but it can have other information as well. This is used if the the app builds the complete coupon itself, otherwise this is optional Optional
BarcodeUrl Optional: Url to the barcode proper. This will have a small white border around it.  Optional
BottomText Optional: Bottom text for the coupon. Optional
BottomImageUrl Optional: URL to a bottom image of a coupon. Optional
BackUrl If present this points to an image to present on the back side of the content. Optional Optional
ThumbUrl If present this points to an smaller representation of the content to be used in an overview display Optional Optional
ContentUrl If content is a HTML based content, this URL is to be opened in the in-app browser. Either TopImageUrl or ContentUrl has to be present Optional
BackgroundColour If present this represents a background colour to use with this coupon. The background colour is represented in #AABBCC notation Optional Optional
Type

 

Content type. 

  • Coupon
  • HTML (this is a link to an HTML page)

If the app feed returns an unknown or unrecognized app type the application should default back on the Coupon type

Mandatory Mandatory
Description The content description. Optional Optional
SubText Optional: A short text to present with the content image. Optional
AmountLeft Optional: If this content has a limited amount of validations, the remaining count is given here. A value of 0 means that no further validations will be possible. If this parameter is not in use the value is empty Optional Optional
ExpiryDate The time/date after which the coupon will be expired. The expiration date/time is given in UTC Mandatory Optional
RatingCategory Optional: The rating category to use. Optional Optional
Id The Id of the Rating category Optional Optional
Name The name of the Rating category (e.g. COFFEE) Optional Optional
ShareType Can take the values ''NotSharable', 'Shareable' or 'ShareAndCare'. If not present then content is not shareable Optional Optional
ValidForStore Optional: If the content can only be used in one particular store, this field has the StoreId value of this store Optional
ValidForStoreTags Optional: A list of all the storeTagIDs where this content can be used. The StoreTags can be resolved to a list of stores. It is up to the app to decide how to display this to the consumer Optional Optional
GiftCardBalance Optional: Balance of the gift card Optional
Activated If true the coupon is already issued/activated. If false only a subset of the coupon object will be returned, and the content must be activated before they can be used True False

 

All images in the coupons will have Last-Modified and E-Tag HTTP-headers to indicate if the image has been updated or not. Use this to check if image in your app should be updated.

GET /content

Gets an overview of all the coupons assigned to a user. This call is primarily used to get an overview of the coupons available to check for changes that have occurred since last time the app was used.

The service expects the following parameters as part of the URL query-string.

 

Parameter
Description
SectionIds Optional: If desirable to only get the content for one or more sections, it can be specified as an array of sectionIds. If not present or empty the response will contain all the available sections
UserId UserId, a unique ID for the given User that is assigned by LIQUID.

 

The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) + UserID + Your secret salt

 

RESPONSE

The service replies with HTTP-200 status when the operation was successful, the body of the response will contain:

 

Parameter Description
Sections Array of sections
Id The Id of the section
Name The name of the section
Content Array of content objects (see Content model) that is placed in this section

Share content

App coupons can be shared to registered users or non-registered members. Sharing to registered users is done app to app. Sharing to unregistered uers is done through any external channel, eg. SMS or other messaging service.

When creating campaigns, dashboard users determine if coupons should be shareable or not. Shareable content is identified using the ShareType parameter in the Content model.

Shareable content can be 'issue new' or 'give away', but this distinction is handled in Liquid Barcodes back end.

Coupon sharing is a one step process.

 

POST /share

Shares some content with the user's friend. This function call should only be used if the content has been assigned as shareable (see content model's ShareType).

The service expects the following parameters as part of the URL.

 

REQUEST

Parameter
Description
ContentId The Id of the content to share.
FriendUserRef The unique user reference to the friend that the user wants to give the coupon to. Normally this is the phone number of the friend (MSN).
ScheduleId LIQUID Barcodes' internal Schedule identifier.
UserId UserId, a unique ID for the given User that is assigned by LIQUID.

 

The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) + UserID + ContentId + Your secret salt

 

RESPONSE

The service replies with HTTP-200 status when the operation was successful, the body of the response will contain:

 

Parameter
Description
Message Optional: The default text to use when the content to be shared should be sent through the user's phone (SMS or some other means). The typical use case is when the recipient has not given consent to the retailer
ResultCode The result of the operation. The following values are supported

Code
Description
SharedOnSms The content has already been shared directly to the friend through SMS
SharedByApp The content has already been shared to the friend's app
SharedByUrl The content has to be shared from the user's mobile phone. The 'Message' parameter contains what needs to be shared
CouldNotShare The content couldn't be shared to the proposed end user.
ResultMessage A human readable text of the result

Rating

Rating allows users to give their opinion on a product they have purchased or the service.

The rating service consists of two types of functions: requests to manage a single user's rating(s) and requests to obtain rating statistics.

When implementing rating functionality in the app, you can choose between making one location in the app to show a dynamic list of all rating types and pending ratings (recommended), or you can make one specific location for each rating type.

 

GET /ratings/categories

Returns all rating categories. Per category also includes the first of any any pending ratings.

The following parameters are expected in the URL query-string:

 

REQUEST

Parameter
Description
UserID UserId, a unique ID for the given User that is assigned by LIQUID.
CategoryId Optional: ID of the rating category to get. If not set, all rating categories with pending ratings will be returned.

 

The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) + UserID + CategoryId + Your secret salt

 

RESPONSE

Upon a successful request the service returns a 200 OK with the following parameters

 

Parameter Description
Categories One object per rating category.
Id Category ID
Name Category name
RatingsSinceReward Number of ratings the user has submitted since last rewarded.
RatingsUntilReward Number of remaining ratings before the next reward.
RatingsPending Number of currently pending ratings. A value of 1 means that only 1 pending rating is available (this one).
PendingRating Optional: If any pending ratings are found for this category, the first (oldest) pending rating is returned here.
RatingId The ID of the rating.
  TimeToLive Time before the rating expires. If value is in the past, it is not possible to rate the product. The time is given in UTC.
Store Details of the store where the pending rating was created / where the product was bought.
Id The ID of the store where the product was bought/redeemed.
Name The name of the store where the product was bought/redeemed.

POST /rating

Submits a user rating for a given rating.

The following parameters are expected in the body of the request.

 

REQUEST

Parameter
Description
UserID UserId, a unique ID for the given User that is assigned by LIQUID.
RatingId The ID of the pending rating. This idea is only available through the previous function call GET /RatingState/
Rating The rating of the product. Any integer value.

 

The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) + UserID + RatingId + Rating + Your secret salt

 

RESPONSE

Upon a successful request the service returns a 200 OK with the following parameters

 

Parameter
Description
Bonus TRUE a reward was given, FALSE otherwise.
Backlog Number of pending ratings that can still be submitted.

GET /ratings/statistics

Gets the statistics for all stores.

The following parameters are expected in the URL query-string:

 

REQUEST

 

Parameter
Description
CategoryId The ID of the category to get the statistics for

 

The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) + CategoryId + Your secret salt

 

RESPONSE

Upon a successful request the service returns a 200 OK with the following parameters

 

Parameter
Description
Array of all stores
StoreId The ID of the store where the product was bought/redeemed.
StoreName The name of the store where the product was bought/redeemed.
Av2MonthRating The average rating for the store going back 2 months.
Tot2MonthRatings The number of ratings for the store going back 2 months.
AvRating The average/current rating of the store all time.
TotRatings The total number of ratings for this store all time.

GET /ratings/statistics/store

Gets the stats for one specific store.

The following parameters are expected in the URL query-string:

 

REQUEST

Parameter
Description
StoreId The ID of the store where the product was bought/redeemed.
CategoryId Refers to a product category.

 

The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) + StoreId + CategoryId + Your secret salt

 

RESPONSE

Upon a successful request the service returns a 200 OK with the following parameters

 

Parameter
Description
StoreId The ID of the store where the product was bought/redeemed.
StoreName The name of the store where the product was bought/redeemed.
Av2MonthRating The average rating for the store going back 2 months.
Tot2MonthRatings The number of ratings for the store going back 2 months.
AvRating The average/current rating of the store all time.
TotRatings The total number of ratings for this store all time.
WeekRatings Array of 9 data points of (week no, average rating) presented in oldest first. The 9th data point is the current week.

Stores management

Liquid Barcodes can store and send a wide range of information per store to the app.

The stores information is typically used to let user select favourite store and store finder.

 

 

Note that only active stores will be available meaning stores that are not closed down for maintenance/refurbishment, closed permanently etc. It is recommended to download the stores list on a regular interval (say 24 hours) and cache it locally, as the store list can be significant amount of data, in addition to it by nature being fairly static.

GET /stores

 

REQUEST

The service has no arguments, but the standard headers.

The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) + Your secret salt

 

RESPONSE

Upon a successful request the service returns a 200 OK with the following parameters (if available)

Parameter Description
Stores List of stores, each object containing:
Id LIQUID internal ID.
ExternalId External (customer's) ID.
Name Name.
ShortName Short name.
Address Address.
Telephone Phone number.
Latitude Geolocation, latitude.
Longitude Geolocation, longitude.
CurrentState The current state of the store. Permitted values are:

  • Open. The store is open for business
  • Closed. The store is not open for business
  • TemporarilyClosed. The store is not open for business but will open again in the future
  • PermanentlyClosed. The store is no longer operational
TagIds Contains a comma separated list of TagIds that are used to group stores
Logo Optional: URL to store logo (if the store uses a different logo from the company logo)
Metadata Contains a comma separated list of key:value pairs related to this particular store. Any keys that the app is unaware of should be ignored
OpeningHours Optional: Array of opening hours, one entry for each way of the week from Monday to Sunday.
Each entry takes the format "H1:M1-H2:M2" where H1/M1 are opening time hours/minutes and H2/M2 are closing time hours/minutes.
For example: "09:00-18:00"
Note Store defined text to signify some special announcements, e.g. 'Closed on Monday due to public holidays'

GET /storetagids

 

REQUEST

The service has no arguments, but the standard headers.

The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) + Your secret salt

 

RESPONSE

Upon a successful request the service returns a 200 OK with the following parameters (if available)

 

Parameter Description
StoreTags List of store tags, each object containing:
Id The ID of the tag/region.
Title The full name of the tag/region.
  StoreIds An array of IDs of all stores that belong to this tag/region.

Recruit-a-friend

The function allows app users to recruit friends to the app and the Recruiter and/or Recruitee can receive reward when the new user registers. It is not possible to recruit already existing users or users that have a pending recruiting attempt.

If new user is not already registered, the app will receive a message text from Liquid Barcodes to prepopulate to the user's preferred native messaging app.

On the recruiting page, make sure that there is an information image (hosted by Liquid Barcodes) that can be updated without app update.

 

GET /validreferral

Checks whether the referral user is already a member or is eligible for referral.
The following parameteres are expected in the URL query-string:
REQUEST
Parameter
Description
UserID UserId, a unique ID for the given User that is assigned by LIQUID.
MSN The MSN of the user that is to be issued a referral

 

The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) + UserID + MSN + Your secret salt

 

RESPONSE

The service replies with HTTP-200 status when the operation was successful (e.g. the MSN is eligible for referral) with the following return values

Parameter
Description
SmsTemplate The template for the SMS text to send to the person being referred 

POST /referral

Allows a user to refer a friend. If the friend registers the app inside a given time period the referral and/or referee is given a reward. This function call should only be called if the mechanism for referral distribution confirms that the referral has been sent (or as close as possible)

The service expects the following parameters as part of the URL.

 

REQUEST

 

Parameter
Description
UserID UserId, a unique ID for the given User that is assigned by LIQUID.
MSN The MSN of the user that is to be issued a referral

 

The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) + UserID + MSN + Your secret salt

 

RESPONSE

The service replies with HTTP-200 status when the operation was successful.

 

Push notification support

Push notifications can have a dramatic positive effect on app opening rates. Liquid Barcodes supports sending push notifications depending on certain events to the app provided that the following steps are completed by the app developer/publisher:

  • iPhone users should be asked to accept push notification as part of the registration process.
  • On Android, and if accepted on iPhone, register the application with the relevant push notification services (Apple, Google, etc)
  • Forward the credentials to Liquid Barcodes. The credentials we require are:
    • Apple push notification service: The iOS Push certificate
    • Google Cloud Messaging (GCM) service: The API key
  • Add functionality to register each instance of the application running on the consumers' devices with the relevant push notification services to obtain the DeviceToken/RegistrationID
  • Every time the DeviceToken/RegistrationID changes, AND upon achieving a successful registration, the app must call the RegisterDevice function described below:

It is very important to test push when releasing new app versions to avoid missing out on push notification registrations.

 

POST /device

This function registers a device with Liquid Barcodes. Note that it is possible to have 0, 1 or many devices associated with a particular UserId (not registered, registered on exactly one device or registered on many devices, respectively). Also for this function we expect the UserAgent HTTP header in the request.

 

REQUEST

Parameter Description
DeviceId A unique identifier for the device that as far as possible is persistent when the user logs in after having a) logged out, b) deleted and re-installed the app, and c) done a factory reset (if possible). This identifier is used to prevent fraud by setting limitations on the number of times a user can use the same device with different MSNs.

Customers using the "Deterministic PIN" feature should instead provide their external user-reference in this field (unique and persistent for a given user).

UserId This is the user identifier for the application. If left blank, the consumer has not yet registered.
DeviceToken The device token assigned to the device upon registering with the appropriate push notification service. If empty, the application user has declined to receive push notifications.
MSN The telephone number the user has registered with.
Language The language setup for the user device according to ISO 639‑1.
DeviceType The device type, where the following values are allowed 'iOS', 'Android'.
AppVersion The version of the application (used to track how many users have upgraded to the latest versions).
Notes Optional: This is a free-text field that can be used to convey any information deemed relevant.

 

The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) + DeviceId + UserId + DeviceToken + MSN + Language + DeviceType + AppVersion + Your secret salt

 

RESPONSE

The service replies with HTTP-200 status when the operation was successful

Receipts handling

Liquid Barcodes stores all receipts in a receipt repository and the app has access to these receipts through our receipts service.

The app can obtain a list of receipts and can ask Liquid Barcodes to forward one or multiple receipts to an email recipient.

 

GET /receipts

The following parameters are expected in the URL query-string.

 

REQUEST

Parameter
Description
UserId UserId, a unique ID for the given User that is assigned by LIQUID.
StoreIds Optional: Will limit the retrieved receipts to this list of stores. Should use the StoreId as available in the GET /Stores/ call
DateFrom Optional: Will limit the retrieved receipts to this datetime and forwards. This is used to get the receipts for the last 6 months f.e.x

 

Note this function call may be slow to respond and the app should be lenient towards any timeouts.

The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) + UserId + Your secret salt

The service replies with HTTP-200 status when the operation was successful with the following return values

 

RESPONSE

Parameter
Description
Array of receipts
Logo Url to company logo Note: If a particular store needs a separate logo, the store logo is available for each store from GET /stores function call
ReceiptId Id of the receipt record (Should be used in POST /receipts/forward)
Format Receipt format, e.g. Liquid/1.0 for this field. The format is detailed below
Receipt

Optional: A JSON representation of the whole receipt for the complete transaction.The JSON should take the following format:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
{
  "ReceiptId":"",
  "TransactionDateTime":"",
  "SubTotal":0,
  "RebateOnSubTotal":0,
  "TenderOnSubTotal":0,
  "TaxAmount":0,
  "TotalToPay":0,
  "Currency":"",
  "Store":{
    "StoreId":"",
    "ExternalStoreId":"",
    "StoreName":"",
    "GLN":"",
    "OrganizationNumber":"",
    "POSId":"",
    "EmployeeId":0,
    "EmployeeName":""
  },
  "Saleslines":[
    {
      "Description":"",
      "EAN":"",
      "ProductCode":"",
      "PLU":"",
      "Quantity":0,
      "Unit":"",
      "Brand":"",
      "SalesPrice":0,
      "Rebate":0,
      "Tender":0,
      "RebatedPrice":0,
      "TaxAmount":0,
      "TaxPercentage":0,
      "Comment":""
    }
  ],
  "Payments":[
    {
      "type":"Card",
      "card_issuer":"",
      "card_issuer_country":"",
      "terminal_id":"",
      "terminal_print":"",
      "transaction_id":"",
      "ref_auth":"",
      "ref":"",
      "auth":"",
      "bax":"",
      "censored_card_number":"",
      "card_token":"",
      "amount":0,
      "tip_amount":0,
      "processing_fee":0,
      "currency":""
    },
    {
      "type":"Cash",
      "amount":20000,
      "tip_amount":0,
      "currency":"NOK"
    }
  ],
  "customer":{
    "id":"",
    "loyalty_id":"",
    "msn":"",
    "name":"",
    "gender":"",
    "birthdate":""
  }
}

Note: The JSON code must be escaped so that the Receipt field is just a regular string.

POST /forward/receipts

Use this service to forward receipts outside the app. The service expects the following parameters.

 

REQUEST

Parameter
Description
MediaType The media to forward the receipts, currently only 'Email' is accepted
ReceiptIds A list of receiptIDs to be forwarded
UserId UserId, a unique ID for the given User that is assigned by LIQUID.
UserReference Optional: The recipient of the receipts. Not necessary if it appropriate information is already stored with the user (e.g. the e-mail address). Note that this value will override any values stored with the user (if the user wants to forward it to another person or another e-mailaddress)

 

The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) + UserId + ReceiptIds + MediaType + Your secret salt

 

RESPONSE

The service replies with HTTP-200 status when the operation was successful.

Shop

The shop allows users to buy content from Liquid Barcodes. The shop provides a set of shop offers that are items that have a defined price and that end users can purchase. The shop functionality consists of three parts:

  • Shop front-end, this is the virtual store where the consumer can choose which products he wants to buy.
  • Shop back-end, this is the handling of the shop items and the issuing of content based on shop transactions.
  • Payment provider, this is a third party payment provider that handles the transaction of real money. If the currency in the shop is loyalty points this can be handled entirely by Liquid Barcodes, otherwise a integration between Liquid Barcodes or third party and the payment provider must be implemented.

Before buying a shop offer, customer must register payment method. This process is payment provider specific.

The interaction flow when buying a shop offer is as follows (where the app is only involved in step 1 to 3 and 5):

  1. The App calls the function ShopOffers and gets a list of offers that can be bought for a certain price by the consumer. This call will provide all the details necessary for the consumer to make a choice, and all the necessary details for issuing coupons.
  2. The consumer selects which offer he wants by putting them into a basket. When buying subscriptions, the app should check any price adjustment with Liquid Barcodes before proceeding to check out.
  3. When checkout of the basket is selected, the app sends a request to the shop back-end using the ProcessShopBasket call.
  4. the app sends request to Liquid Barcodes with shop offer to purchase and preferred payment option. Liquid Barcodes back-end, that is integrated towards the payment provider, will request the baskets grand total to be reserved by the payment provider (note that this is not the actual payment, but reserving an amount of money on the consumers account).
    • The shop back-end will check that the request is valid and represents the offers that was provided in GET /shopoffers. This is to prevent tampering.
    • Dependent on the third party payment provider the request will be processed synchronously (SuccessCode = OK) or asynchronously (SuccessCode = InProcess). If processed asynchronously the app needs to request the status using GET /ShopTransactionStatus
  5. Appropriate information should be given to the user that the process has completed, how much was paid and, if any, which coupons could not be issued.
  6. When payment has been reserved, one or multiple actions can be triggered in Liquid Barcodes system, such as starting a subscription, issuing a coupon or topping up a gift card. When actions are complete, Liquid Barcodes will confirm payment with the payment provider. On error, Liquid Barcodes will cancel payment.

Liquid Barcodes also support payment provider integrations by third parties. Read more about this under Customer integrates with payment provider.

Dashboard users can create shop offers and the related actions. Each shop offer has a unique shop offer token that serves to define the shop offer and add security.

When content has been issued, Liquid Barcodes updates the unique user's content record if relevant. The app shows the purchased content as described under Content management.

Receipts from successful purchases can be obtained as described under Receipts handling.

 

Shop offer model

This is the structure of the objects served in the GET /shopoffers request:

 

Parameter
Description
ShopOfferId The unique ID for this particular offer.
PaymentProviderId The ID of the payment provider where the OfferToken must be sent.
MaximumAmount The maximum number of times the offer can be bought. If not present or NULL it means unlimited
ThumbUrl If present this points to an smaller representation of the shop offer to present on f.ex the front page of the application.
Url URL to the offer details image.
BackgroundColour If present this represents a background colour to use with this coupon. The background colour is represented in #AABBCC notation.
Type Defines the type of shop offer. Can take two values 'Shop' and 'Local'
LocalData Optional: If type is Local this section is mandatory (not implemented)
StoreId The StoreId that the local shop offer can be used
RemainingOffers The number of remaining offers
PickupStartDateTime The earliest time/date this offer be be picked up. The date/time is given in UTC.
PickupEndDateTime The latest time/date this offer be be picked up. The date/time is given in UTC.
Description A textual description of the shop offer.
ProductDescription A textual description of the shop offer.
PurchaseConfirmation A textual description of the shop offer.
ExpiryDate The time/date when this offer is no longer available . The expiration date/time is given in UTC.
RetailPrice The price to the consumer.
Currency Will always be the currency of the app's country (one app, one country).
OfferToken Deprecated: This is the token that represents the offer for this user. The OfferToken will be used to trigger coupons between the App vendor and Liquid Barcodes backends. NOTE: All the offer tokens will expire according to the OfferTokensExpiration field below.
OfferInstanceId The unique instance ID for each individual shop offer

Register payment method

Before customers can start buying items in the shop, customer must register payment mothod. The process may vary depending on the chosen payment service provider.

 

GET /PaymentConfiguration

 

GET /shopoffers

Gets an overview of all the offers available in the shop for this user. This call is primarily used to get an overview of the shop offers that are available.

The service expects the following parameters as part of the URL query-string:

 

REQUEST

Parameter
Description
UserID UserId, a unique ID for the given User that is assigned by LIQUID.
CategoryIds Optional: If desirable to only get the shop offers for one or more categories, it can be specified as an array of CategoryIds. If not present or empty the response will contain all the available categories

 

The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) + UserID + Your secret salt

 

All images referred to in the response will have the HTTP headers Last-Modified and E-Tag set and the app should use this to detect when images have changed (do a HEAD request for the images).

The service replies with HTTP-200 status when the operation was successful, the body of the response will contain:

 

RESPONSE

 

Parameter
Description
Categories Array of categories
Id The Id of the category
Name The name of category
ShopOffers Array of content objects (see Shop offer model) that is placed in this category
OfferTokensExpiration The expiration time for included offer tokens in this category. After this time the offer tokens will be invalid. A new set of shop offers must be fetched to supply the user with fresh offer tokens.

GET /shopcategories

Returns all shop offer categories.

 

REQUEST

The service has no arguments but the standard headers.

The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) + your secret salt.

 

Upon a successful request the service returns a 200 OK with the following parameters

 

RESPONSE

Parameter Description
Categories List of shop offer categories, each object containing:
CategoryId The Id of the category
CategoryName The name of category

POST /ProcessShopBasket

This will process the basket of specified shop offers and withdraw credits from the account associated with the user.  Each call to this function is a separate purchase transactions for the user.

 

REQUEST

 

Parameter Description
UserId The UserId of the user
StoreId Optional: The Liquid Barcodes storeId is required if the offer can only be used at a given store.
PaymentProviderId The Liquid Barcodes Payment Provider Id. The appropriate value to use here will be provided by Liquid Barcodes
PaymentInformation Optional: Any information that is necessary to process the transaction with the payment provider, an example could be the payment provider session if this session is started from the app. This parameter is an array of Key:Value pairs.
TotalBasketValue The total value of the basket. This is used to control that what has been presented to the consumer matches the offers to be processed
ShopOffers An array of shop offers tokens that are to be processed.
OfferInstanceId The offer instanceId that is unique for this shop offer and UserId
Amount The number of products to buy. This parameter have a value between 1 and MaximumAmount set in the shop offer

 

The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) + UserId + PaymentProviderId + TotalBasketValue + Concatenated(OfferInstanceId + Amount) + Your secret salt 

A successful call will return a HTTP 200 OK with the following format
 RESPONSE
Fieldname Title Description
TransactionId Transaction reference A reference to LIQUIDs internal transactionID.
Timestamp Transaction timestamp The date and time when the reservation was completed.
TotalValue Total transaction value This is the total value that is used for the transaction
ShopOffers Optional: An array of shop offers tokens that are to be processed. The array is only present if the order has been fulfilled
OfferInstanceId Offer instance ID The offer instance Id that was purchased
Amount Amount The number of products bought.
SuccessCode Success code Optional: On success returns

  • OK - The purchases was completed synchronously and the transaction is finalised
  • InProcess - The order is currently processed. The status of the order can be checked with GET /ShopTransactionStatus
SuccessMessage Success message Optional.  A human readable response message when the call was successful. Only set when SuccessCode is set.
RejectCode Reject code Optional. A code that can be used to programatically recognize the cause of a rejection. Either SuccessCode or RejectCode will be present in the response.

The following values can occur:

  • PriceChanged. The app needs to get updated pricing information and re-issue ProcessShopBasket
  • NothingIsSelected. ShopOffers collection is empty
  • WrongPaymentProvider. The appropriate value to use here will be provided by Liquid Barcodes
  • TotalBasketValueNotMatch. This is used to control that what has been presented to the consumer matches the offers to be processed
  • WrongStore. ShopOffer can only be used at another store
  • InvalidAmount. ShopOffer is configured with MaximumAmount
  • WrongUser. UserId in request is wrong
  • UnknownError. Some server error
RejectMessage Reject message Optional. A human readable cause of rejection message in case a rejection occurred. Only set when RejectCode is set.

GET /ShopTransactionStatus

Can be called to check the status of the transaction at a later stage.

 

REQUEST

 

Parameter Description
UserId The UserId of the user
TransactionId A reference to LIQUIDs internal transactionID.

 

The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) + UserId + TransactionId + Your secret salt

A successful call will return a HTTP 200 OK with the following format

 

RESPONSE

Fieldname Title Description
TransactionId Transaction reference A reference to LIQUIDs internal transactionID.
Timestamp Transaction timestamp The date and time when the reservation was completed.
TotalValue Total transaction value This is the total value that is used for the transaction
ShopOffers Optional: An array of shop offers tokens that are to be processed. The array is only present if the order has been fulfilled
OfferInstanceId Offer instance ID The offer instance Id that was purchased
Amount Amount The number of products bought.
SuccessCode Success code Optional: On success returns

  • Fulfilled - The order has been fulfilled
  • InProcess - The order is currently processed. The status of the order can be checked with GET /ShopTransactionStatus
SuccessMessage Success message Optional.  A human readable response message when the call was successful. Only set when SuccessCode is set.
RejectCode Reject code Optional. A code that can be used to programatically recognize the cause of a rejection. Either SuccessCode or RejectCode will be present in the response.

The following values can occur:

  • PriceChanged. The app needs to get updated pricing information and re-issue ProcessShopBasket
  • NothingIsSelected. ShopOffers collection is empty
  • WrongPaymentProvider. The appropriate value to use here will be provided by Liquid Barcodes
  • TotalBasketValueNotMatch. This is used to control that what has been presented to the consumer matches the offers to be processed
  • WrongStore. ShopOffer can only be used at another store
  • InvalidAmount. ShopOffer is configured with MaximumAmount
  • WrongUser. UserId in request is wrong
  • UnknownError. Some server error
RejectMessage Reject message Optional. A human readable cause of rejection message in case a rejection occurred. Only set when RejectCode is set.

Customer integrates with payment provider

Use this flow if you want to integrate towards the payment provider or if you manage your own payment service (eg. your own points program or private label gift cards)

The structure of the shop transactions is the same as for the Shop solution where Liquid Barcodes integrates with payment provider with one main distinction: when customer has decided on product(s) to buy and payment has been reserved, the app should  decrypt the outer offer token for each product to compare paid amount and listed product prices. Stop transaction on mismatch.

 

Code usage

The function allows app users to enter a code in the app to get reward, transfer stamps from paper loyalty card to app and many other functions.

In most use cases, the app should only send code to Liquid Barcodes back end. The issue of the correct reward or other action is handled by Liquid Barcodes back end.

 

 

POST /code/usage

This allows the app to use codes issued by Liquid Barcodes. The effect of such a usage is controlled entirely by Liquid Barcodes system.

 

REQUEST

Parameter Description
UserId The UserId of the user
TransRef A 'unique' reference to this transaction. If several ReserveCodes call use the same transaction reference it means that the redemption of these codes should be considered a single transaction
Code  The code to be reserved
StoreId Optional: If the app is simulating a redemption from a store the StoreId must be present
Position Optional. An attempt to acquire geographical location.
Should be set whenever an attempt to acquire location was made. In this object you must set either Position or ErrorCode+Error.
Position Optional. Must be set when the attempt to acquire geographical location succeeded.
The position will be used to attempt identification of which store performed the reservation.
Position is given as decimal degrees (DD). Conversion from sexagesimal (DMS): With degrees, add minutes as /60 fractions, add seconds as /3600 fractions.
Longitude Longitude / meridian. Range from -180.0 (180 degrees west) to 180.0 degrees (180 degrees east).
Latitude Latitude / parallel. Range from -90.0 (south pole) to 90.0 degrees (north pole).
Accuracy Optional. The accuracy for the position in meters.
Altitude Optional. Altitude in meters, relative to sea level.
AltitudeAccuracy Optional. The accuracy for the altitude in meters.
Speed Optional. Current velocity of the device in meters per second.
Heading Optional. Current heading in degrees of clockwise deviation from heading true north (which means that 0, 90, 180, 270 degrees is north, east, south and west, respectively).
ErrorCode Optional. Must be set when the attempt to acquire geographical location failed.
Error classification. One of: PermissionDenied, Unavailable, Timeout, NotSupported, Unknown.
Error Optional. Must be set when the attempt to acquire geographical location failed.
Error message / details. May be a blank string if there are no further details that ErrorCode.

 

The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) + UserId + TransRef + Code + Your secret salt 

A successful call will return a HTTP 200 OK with the following format
RESPONSE

 

Fieldname
Title
Description
LiquidLogRef Log reference A reference to LIQUIDs internal logs.
UniqueCode Unique coupon code The reserved unique coupon code.
Timestamp Reservation timestamp The date and time when the reservation was completed.
Value Reservation value Optional: The monetary value of the reservation
SuccessCode Success code Optional. The success code that can be used to programmatically recognize the successful result of the operation. Either SuccessCode or RejectCode will be present in the response.
SuccessMessage Success message Optional.  A human readable response message in case the codes was used. Only set when SuccessCode is set.
RejectCode Reject code Optional. A code that can be used to programatically recognize the cause of a rejection. If this field is set it means that the reservation has failed, all other values for this reservation must be disregarded. Either SuccessCode or RejectCode will be present in the response. (Our suggested user response in italic and brackets)

The following values can occur:

  • CustomerMismatch, (Invalid code), the requested UniqueCode belongs to a campaign that is not associated with the authenticated user.
  • CampaignInactive, (Invalid code), the requested UniqueCode belongs to a campaign that is no longer / not yet active.
  • CampaignOncePerSaleOnly, (Invalid code), the campaign setup demands that the UniqueCode can only be used once per receipt and this requirement was not fulfilled.
  • ReservationCountTooHigh, (Code is depleted), too many unvalidated+uncancelled reservations exist for this UniqueCode.
  • ScheduleInactive, (Invalid code), the requested UniqueCode belongs to a campaign that is no longer / not yet active.
  • ScheduleStoreMismatch, (Wrong store), the UniqueCode was issued for use in a specific store, this requirement was not fulfilled.
  • ScheduleNoRemainingValidations, (Campaign is depleted), the campaign has a limited amount of validations and there are no validations left.
  • CodeInactive, (Code has expired), the requested UniqueCode has expired.
  • CodeAlreadyUsed, (Code is depleted), the requested UniqueCode only allows one validation and is already validated.
  • CodeNotFound, (Invalid code), the requested UniqueCode is invalid.
  • CodeDepleted, (Code is depleted), the requested UniqueCode has already been used the maximum number of allowed times
  • DailyValidationsExceeded, (Code is depleted today), the code has reached or exceeded the maximum number of validations per day.
  • Blocked, (Code has expired), the code or campaign has been blocked. Used when phasing out a campaign, for example.
RejectMessage Reject message Optional. A human readable cause of rejection message in case a rejection occurred. Only set when RejectCode is set.

List of errors

The raw error ID can be read from the X-Liquid-ErrorId HTTP header.

 

Error ID
HTTP Status
Services
Description
0 500 0 Any. Unknown error, contact Liquid Barcodes.
1 401 1 Any. The signature in the X-Liquid-Signature HTTP header was wrong.
2 401 2 Any. The timestamp in the X-Liquid-Timestamp HTTP header was not parsable or had more than 10 minutes deviation from our current time.
8 500 8 Any. Unauthorized access. User either not exists or not allowed to use app.
10 500 10 POST /pin Failed to send PIN.
12 500 12 POST /user Incorrect PIN.
13 500 13 POST /user Expired PIN.
14 500 14 POST /user Msn is blocked. More than 5 attempts to input pin where made. User should wait until PIN will be expired.
22 500 22 POST /user Cannot find device ID for the user.
23 500 23 GET /validreferral
POST /referral
Too many recruitment attempts.
33 500 33 POST /pin Too many MSNs has been used from the same device.
34 500 34 GET /validreferral

POST /referral

Missing or invalid MSN.
44 500 44 PUT /user Failed to update user profile.

The response body is an array of UserGroups that wasn't processed + ErrorCode + Message, with error description:

1001 Can't validate code [UserCode] for group tag [GroupId].
1002 Can't find active group for tag [GroupId]
1003 Can't quit group [GroupId], because user is not member of this group
1004 Group [GroupId] is not user configurable

45 500 45 POST /initialize Missing or invalid Device ID.
47 500 47 POST /user Minimum age not met.
48 500 48 Any. A service requires master consent approval before it can be used.
49 500 59 Any. Reset user exception. The user has been marked for a reset, force a new POST /initialize, POST /pin, POST /user.
50 500 45 POST /share Missing or invalid Schedule ID.
51 500 51 POST /referral Attempted to refer a MSN that was not referable.
52 500 52 POST /device Missing or invalid language code.
53 500 53 POST /device Missing or invalid device type.
54 500 54 POST /device Missing or invalid app version.
55 500 55 POST /user Invalid PIN.
56 500 56 POST /user Invalid person name.
57 500 57 POST /user Invalid address.
58 500 58 POST /user Invalid city.
59 500 59 POST /user Invalid post code.
60 500 60 POST /user Invalid email.
61 500 61 POST /user Invalid date of birth, should be yyyy-mm-dd.
62 500 62 Any with UserId. Missing or invalid User ID.
63 500 63 ValidateScratchCard Invalid card ID.
64 500 64 POST /code/usage Invalid code
65 500 65 POST /receipts/forward Provided list of receipt Ids is empty
66 500 66 POST /receipts/forward Member doesn't have valid e-mail and we can't send him message

Change log

 

Here is a list of all updates to the App API:

 

version 3.0.4
- Added function to validate codes through the app

version 3.0.3
- Added functionality to process the shop basket through Liquid Barcodes (and not a 3rd party)
- Deprecated OfferToken in Get /ShopOffers (replaced with OfferInstanceId)

version 3.0.1
- Added shop offer category
- Corrected typos

version 3.0.0.1

GET /ratings/categories
- Added CategoryId
- Removed ProductCategory

POST /Ratings
- Added RatingId
- Removed StoreId

version 3.0.0

Change log Unified app feed

General
- All signatures are using SHA-2 256
- Deterministic PIN follows the same registration flow (POST /initialize => POST /pin => POST /user)
- The registration process has significantly changed to accommodate GDPR requirements
- All GET calls now takes the syntax /somefunction?parametername1=parametervalue1&parametername1=parametervalue2
- When mandatory consent has not been given, all functions apart from the registration functions will return a corresponding error code
- When the user needs to be forced to re-register, all functions apart from the registration functions will return a corresponding error code

POST /app
- Name change to POST /initialize
- InstanceId parameter has been removed
- UDID has changed name to DeviceId
- Optional culture parameter when app supports multiple languages (consent text needs to be presented in multiple languages)

POST /pin
- Now used also for deterministic pin applications (returns the PIN in the response)

POST /user
- Emails parameter support multiple emails (array)
- Deprecated PreferredStore is no longer supported
- Can set SelectedPreferredStore from the app (the user's preference)
- Parameters for ApprovedConsents and Revoked consents added
- The response returns the entire user model

PUT /user
- See POST /user

GET /User
- Changed syntax (see general section)
- Emails parameter support multiple emails (array)
- Deprecated PreferredStore is no longer supported
- will get SelectedPreferredStore from the app (the user's preference)
- Parameters for ApprovedConsents and Revoked consents added
- The response returns the entire user model

User Model
- Includes both the PreferredStores (allocated by the system) and SelectedPreferredStores (selected by the user)
- emails parameter includes all emails
- User's selected culture is now included
- The status of all current consents (whether approved or revoked) is returned
- Link to HTML page where the user can get the complete personal details is included

GET /languages
- Changed syntax (see general section)

Coupon object
- Renamed to Content model
- Deprecated CampaignId has been removed
- CouponId is renamed to ContentId
- Deprecated URL has been removed
- TopCouponImageUrl changed name to TopImageUrl
- TopCouponText changed name to TopText
- BottomCouponText changed name to BottomText
- BottomCouponImageUrl changed name to BottomImageUrl
- OverlayURL has changed name to ContentUrl
- Type options has reduced to Coupon and HTML
- Deprecated Version has been removed
- ProductCategory is replaced by the RatingCategory is associated with this content. The RatingCategory includes Id and Name
- Shareable parameter has been replaced by ShareType
- Optional parameter GiftCardBalance has been added
- Activated parameter has been added (currently always true)

GET /coupons
- Changed syntax (see general section)
- Changed name to GET /content
- Complete parameter has been replaced by array of SectionIds
- Returns an array of sections with Id, Name and array of content
- Reset user response is now included as an error code

GET /coupons/group
- Removed

Get Location Based Coupons
- Removed

GET /coupon
- Changed to a POST function
- Changed name to POST /share
- Changed CouponId to ContentId

GET /RatingState
- Changed syntax (see general section)
- Changed name to GET /ratings/categories
- The response contains an array for the first rating opportunity per rating category
- RatingAvailable has been replaced by PendingRating parameter
- Response has been reorganised and parameters renamed

POST /RateProduct
- Changed name to POST /rating
- AppId has been removed
- ShopId has changed name to StoreId

GET /ratings
- Changed syntax (see general section)
- Removed UserId and Appid as parameters are not needed
- ShopId has changed name to StoreId

GET /StoreStats
- Changed syntax (see general section)
- Removed UserId and Appid as parameters are not needed
- ShopId has changed name to StoreId
- ProductCategory has changed name to CategoryId
- ShopName has changed name to StoreName

GET /Stores
- Changed syntax (see general section)
- UserId removed as parameter no longer needed
- Deprecated Tag parameter has been removed

GET /StoreTags
- Changed syntax (see general section)
- Has changed name to GET /storetagids
- UserId removed as parameter no longer needed
- Deprecated Tag parameter has been removed

GET /validreferral
- Changed syntax (see general section)

POST /referral
- No change

POST /device
- No change

GET /receipts
- Changed syntax (see general section)

GET /shopoffers
- Changed syntax (see general section)
- Added MaximumAmount parameter
- Added Local shop offer parameters

List of errors
- Added ConsentAgeException (47), ConsentException (48) and ResetUserException (49) error codes

 

version 2.1.12

- Corrected email type in the specification

version 2.1.11
- Changed all signature calculations to SHA-2 256 variant (MD5/SHA-1 will continue to work for a time period)

version 2.1.8
- Allows the MSN to be set on the user (only when using deterministic/static pin)

version 2.1.7
- Added additional error codes

version 2.1.6
- Corrected underlying functionality to support ShareByUrl instead of SharedByUrl

version 2.1.5
- Corrected typo in ShareByUrl to SharedByUrl
- Added error ID 46: blacklisted user

version 2.1.3
- Clarified the use of Get / coupon calls

version 2.1.2
- Clarified the use of External StoreId/ShopId in the PUT/POST /User calls

version 2.1.1
- Formatting changes
version 2.1.0
- Added Shop function to display a list of coupons that can be bought in a virtual store
- Added functionality to display receipts in the app
- Added functionality to forward receipts from the app
- Added optional logo field on the Stores data
- Fixed an issue with the new share function

Coupon API

 

 

 

Introduction

The Coupon API allows third parties to issue and obtain various types of content on Liquid Barcodes platform.

 

  • IssueRequest, will automatically issue the specified content, eg. a coupon, a game or a survey, to an existing user in the Liquid Barcodes system.
  • GetContent, will retrieve a content object, most often a coupon, that can be distributed in the way the caller prefers.
  • Reports, a mechanism to retrieve reports of the activity.
  • Transaction/reserved, a mechanism to issue coupons based on a purchase in a virtual shop.

General principles

Background

This document describes the application interface to issue coupons, or other content, to an individual users or to get a coupon for other distribution. This provides an easy way for 3rd parties to send out coupons from given campaigns to consumers of their choice. The campaigns have to be agreed upon beforehand, and the API only allows coupons for these campaigns.

Nomenclature

coupon gives user right to a financial discount or rebate when purchasing a product. A coupon can take many forms, such as single use rebate coupons, loyalty cards, reward coupons, limited coupons etc. All these should be treated equally by the app.

HTML based content is some content that is displayed in the in-app web browser, for example games, surveys and weblink images. Common to all these content types is that user is presented with an image that works like a button to open the HTML content.

Shop offer: a content object that end users can buy. Purchasing these items will trigger issue of related content, eg. coupons or gift card balance top up.

A TransactionID is an ID generated by the caller for these functions. The TransactionID should be unique for each call for a give ScheduleId

Any field that is marked with Deprecated, is obsolete but is present to maintain backwards compatibility. It can at any moment be removed from this API, and shouldn't be used

Headers

 

The recommended content type for the requests sent to our services is JSON, i.e. HTTP header Content-Type: application/json.

For every service request the following HTTP headers must be present:

  • X-Liquid-TimeStamp– date in ISO-8601 format. e.g. 2014-03-06T13:11:04Z
  • X-Liquid-Signature - signature calculated in the manner described below.

Note that a difference of more than 15 minutes between the current time and the DateTimeHeader will be rejected

Security

You are intended to connect to this API through your server and not directly from a webclient, In particular all code that is handling the calculation of signature and the security mechanisms of this API has to be done on the server side, Failure to implement it in such fashion means that we can disable you access at any point at Liquid Barcodes discretion.  Also your implementation should be designed in such a way that re-enginering the webclient by 3rd parties are not able to create a 'infinite' coupon generator. Safety mechanisms should be put in place, e.g. a limit to the number of attempts from a given computer over a specific session etc.

 

All calls rely on HTTP Basic Authorization, and username and password are provided by LIQUID.  The security credentials and additional details (the salt) is available on request.

Signature calculation

The services require the use of an SHA-2 256 checksum of the X-Liquid-Date header, one or more request parameters and a secret salt. The salt is known only by LIQUID and the customer. Each of the service definitions in the next chapter will specify which parameters should go into the checksum calculation.

 

Example: 

  • The current UTC timestamp is 2014-03-06T13:11:04Z
  • The secret salt is liquid1234
  • The parameters used for this example functions are:
    • ParameterA = 5824
    • ParameterB = abcd
    • ParameterC =99

The calucation of the SHA-2 256 signature is given by (detailed in each function call):

  • SHA-2 256 checksum of: Timestamp + ParameterA + ParameterB + ParameterC + Your secret salt
The source for the checksum would then be:

SHA-2 256("2014-03-06T13:11:04Z5824abcd99liquid1234") = ae76588d46686f300efba39d674d178863607f654f22d00a6cb4e9ba05d73e4f

Signature Debugging Tool

Request Liquid Barcodes to issue content

The Coupon API – IssueRequest is a web service that allows you to issue one specific coupon at a time to one specific user using Liquid Barcodes’ distribution mechanisms. This can be Liquid Barcodes’ app-API (see above, Liquid Barcodes will populate the user’s record with the correct coupon) or Liquid Barcodes’ SMS handler. When calling the IssueRequest, the key information you provide is which coupon you want (schedule ID), which user should receive the coupon (UserReference) and your credentials.

 

POST /IssueRequest

 

Service: https://api.barcodes.no/v3/IssueRequest

 

REQUEST

 

Parameter
Description
BottomSMSText Deprecated: A text that is to be inserted after the SMS content that LIQUID provides. Will only be used when issuing coupons. Must be in accordance with the GSM 03.38 character set. Only applicable if Destination = 'SMS'
Culture Optional: The culture that should be used for issued instance (Culture should be supported by customer, if not - exception will be thrown).
ExpirationDate Optional: The expiration date of the coupon. Note this date cannot precede or exceed the campaign start and stop dates. In case of conflict the expiration date will be moved to fit inside the period (if possible). If left out the default expiration date will be used (either static or a certain time period from the date of issue)
ExternalRef Optional: A reference that identifies the call in a meaningful way for the caller. The value here will be propagated all the way to the reports that gets generated.

Key
Value
Customer chosen key Customer chosen value
... ...

 

ScheduleId LIQUID Barcodes' internal Schedule identifier.
TopSMSText Deprecated: A text that is to be inserted before the SMS content that LIQUID provides. Will only be used when issuing coupons. Must be in accordance with the GSM 03.38 character set. Only applicable if Destination = 'SMS'
TransactionId The transactionID for this transaction. Must be an ID that identifies this transaction uniquely
UserRef The unique reference to the user. The only accepted value is a Liquid Barcode generated UserId, e-mail or an MSN (Note that MSN should be formatted with the country code i.e. 4798765432 for Norway).

 

The signature is calculated as an SHA-2 256 checksum of: X-Liquid-Date header + ScheduleId + UserReference + TransactionId + Your secret salt

If the service fails it will reply with a non-HTTP-200 response or a response where RejectCode is set.

 

RESPONSE

 

Parameter
Description
RejectCode Optional: A code that can be used to programatically recognize the cause of a rejection. If this field is set it means that the reservation has failed, all other values for this reservation must be disregarded.

The following values can occur:

  • NoContentIssued - the content was not issued
  • Exception - when there were unpredictable exceptions during the issue
RejectMessage Optional: A human readable cause of rejection message in case a rejection occurred. Only set when RejectCode is set.

Get content from Liquid Barcodes

The Coupon API – GetContent is a web service that allows you to obtain one specific coupon, survey or game at a time for your own distribution. When calling the GetContent service, the key information you provide is which content you want (schedule ID), which user should receive the coupon (UserReference) and your credentials. Liquid Barcodes will then respond with a coupon, survey or game object, from which you can select the relevant information necessary for your distribution.

 

How to build a coupon image

The coupon image can be built with the following five elements:

  • TopCouponImageUrl
  • TopCouponText
  • BarcodeImageUrl
  • BottomCouponText
  • BottomCouponImageUrl (Often not present)

You are required to use all 5 elements to depict the coupon for each element that is present. The coupon image can be build the following way:

 

 

POST /GetContent

Some content will be generated the requested schedule, and is available for discretionary distribution.

Service: https://api.barcodes.no/v3/GetContent

 

REQUEST

Parameter
Description
Culture Optional: The culture that should be used for issued instance (Culture should be supported by customer, if not - exception will be thrown).
ExternalRef Optional: A reference that identifies the call in a meaningful way for the caller. The value here will be propagated all the way to the reports that gets generated.

Key
Value
Customer chosen key Customer chosen value
... ...

 

MediaType The media type the coupon is going to be used for. Valid values are 'SMS', 'App', 'email' and 'print'.
ScheduleId LIQUID Barcodes' internal Schedule identifier.
TransactionId The transactionID for this transaction. Must be an unique ID
UserRef Customers reference for the recipient of this coupon. It is important that this parameter is an actual unique user reference, as some campaigns will return the same coupon instance

The signature is calculated as an SHA-2 256 checksum of X-Liquid-Date header + ScheduleId + TransactionId + MediaType + UserRef + Your secret salt

A successful call will return a ContentObject as described below.

 

RESPONSE

Parameter
Description
RejectCode Optional: A code that can be used to programatically recognize the cause of a rejection. If this field is set it means that the reservation has failed, all other values for this reservation must be disregarded.

The following values can occur:

  • NoContentIssued - when no coupons were issued
  • IncorrectConfiguration - The configuration is incorrect
  • ContentUnavailable - when coupon already expired or is missed
RejectMessage Optional: A human readable cause of rejection message in case a rejection occurred. Only set when RejectCode is set.

 

CONTENT OBJECT

Parameter
Required for
Description
AmountLeft All Shows the number of times this content can be used.
BarcodeImageUrl Coupon Url to a scannable image that represents the UniqueCode. This will have a small rectangular area of white around it. May include the unique coupon code below the barcode. This is a required component of the coupon
BottomCouponImageUrl Coupon Optional: URL to a bottom image of a coupon. If present this is a required component of the coupon
BottomCouponText Coupon Optional: Bottom text for the coupon. If present this is a required component of the coupon
ContentId All LIQUID Barcodes internal content identifier.
ContentType All Will return the content type. Currently the only allowed values are 'Coupon', 'Survey', 'Games' and 'HTML'
ContentUrl: Coupon, Survey, Game, HTML The URL to the complete content as a prepackaged html file (this HTML file references the above five fields)
Description All A textual description of the coupon.
ExpiryDate All The time/date after which the content will expire.
ScheduleId All LIQUID Barcodes' internal scheduleID identifier.
TopCouponImageUrl Coupon Optional: URL to the top image part of the coupon. If present this is a required component of the coupon
TopCouponText Coupon Optional: Top text for the coupon which can be 1-3 lines of text. The most common use of this parameter is the text "Valid to ...", but it can have other information as well. If present this is a required component of the coupon
UniqueCode Coupon The unformatted unique code

Get report from Liquid Barcodes

The Coupon API – Get Report is a web service that allows you to get various raw data sets for a specific period (day, week, month, quarter, year). The file format is csv.

POST /report

Will fetch the specified report. The standard format of the report is a csv file.

 

Service: https://api.barcodes.no/v3/Report

 

REQUEST

Parameter
Description
ReportName The name of the report. Currently the following reportnames are supported (required parameters in bracket):

  • CouponIssueReport (Period, Date)
  • CouponValidationReport (Period, Date)
  • GameIssueReport (Period, Date)
  • GamesPlayReport (Period, Date)
  • SettlementReport (Period, Date)
  • MembersReport (none)
  • CouponCampaignIssueReport (ScheduleId) NOT IMPLEMENTED
  • CouponCampaignValidationReport (ScheduleId)
  • GameCampaignIssueReport (ScheduleId) NOT IMPLEMENTED
  • GameCampaignPlayReport (ScheduleId) NOT IMPLEMENTED
  • SurveyCampaignReport (ScheduleId)
Period Optional: The period for the report. Currently the following options are supported: 'Day', 'Week', 'Month', 'Quarter'.
Date Optional: The startdate for the report. The date should be the first day in the period you request, e.g. period = 'Month' and Date = '2015-07-01' would give you the report for July 2015.
ScheduleId The ScheduleID for the campaign you want the report for

 

Checksum calculated from: X-Liquid-Date header + ReportName + Period + Date + ScheduleId + Your secret salt

A successful call to this function will return the following:

 

 

RESPONSE

Parameter
Description
ReportLink Optional. Link to the requested report
ResponseCode Optional. A code that can be used to programatically recognize the state of response.

The following values can occur:

  • Ok - report is ready and field ReportLink should be filled
  • GeneratingReport - report is not ready yet and is being generated.
ResponseMessage Optional. A human readable state of response.

 

If report does not exist service replies with ResponseCode "GeneratingReport" and report generation will be started, you can either re-try the request in 10 minutes or you can use the Coupon Event API to register a listener and get a callback when the report is ready .

If the service fails it will reply with a non-HTTP-200 response or a response where RejectCode is set:

 

 

Parameter Description
RejectCode Optional. A code that can be used to programatically recognize the cause of a rejection.

The following values can occur:

  • NotFound - when report can't be found
RejectMessage Optional. A human readable message for the cause of rejection.

Ask Liquid Barcodes to issue content purchased in shop

NOTE: this service should only be used when Customer integrates with payment provider.

The following paragraph describes the functionality required to issue a coupon based on a purchase in your app. This functionality consists of three parts:

  • Shop front-end, this is the virtual store where the consumer can choose which products he wants to buy.
  • Payment provider, this is a third party or a back-end to a payment provider that handles the transaction of real money. This part needs to communicate with the app once the user has selected a particular offer to purchase. This part is not part of the existing Liquid Barcodes offering
  • Issuing purchased coupons, this is a function of the Liquid Barcodes Coupon API that enables the payment provider to issue the coupon that was purchased to the user's app. The issued coupon will appear in one of the four sections available through Get /coupons. Only this part of the shop functionality is described in this document

The interaction flow for the while process is as follows (where this document only handles step 5 )

  1. The App calls the function ShopOffers and gets a list of offers that can be bought for a certain price by the consumer. This call will provide all the details necessary for the consumer to make a choice, and all the necessary details for issuing coupons.
  2. The consumer selects which offer he wants by putting them into a basket.
  3. When checkout of the basket is selected, the app sends a request to the App provider's back-end for execution of the order.
  4. The back-end will request the baskets grand total to be reserved by the payment provider (note that this is not the actual payment, but reserving an amount of money on the consumers account).
    1. If the step above fails, an appropriate payment-related error message should be provided to the consumer, and the process aborted.
  5. For each item on the order, the App provider should contact LB server to issue each individual coupon. Use the Coupon API for these requests. For each call the response will be either:
    1. Coupon has been issued successfully and should be counted towards the final payment.
    2. Coupon is not issued successfully and should not be counted towards the final payment.
  6. The App provider's back-end should commit the final transaction value to the payment provider.
  7. Appropriate information should be given to the user that the process has completed, how much was paid and, if any, which coupons could not be issued.

POST /transactions/reserved

NOTE: this service should only be used when Customer integrates with payment provider.

After a payment has been completed the payment provider must make a request to this service. Make sure to check paid amount versus product price from Liquid Barcodes. Liquid Barcodes will then issue coupons accordingly.

 

Service: POST https://api.barcodes.no/v3/transactions/reserved

 

REQUEST

Parameter
Description
PaymentProviderId The payment provider ID received in the offertoken from the app.
PaymentRef A reference to the completed transaction in the payment providers system. Will be used when contacting the payment provider for support issues.
InternalOfferTokens The list of internal offer tokens, still encrypted, received in the payment providers decrypted offer token. Only the tokens of the items that were successfully paid must be included.

 

The SHA-2 256 signature is calculated from X-Liquid-Date header + PaymentProviderId + all InternalOfferTokens (concatenated, separated by nothing) + Your secret salt

 

The service replies with a status per InternalOfferToken.

 

RESPONSE

 

Parameter
Description
LogReferenceId An ID of our internal logs, the payment provider should ideally link this to the payment. Should be used when contacting LIQUID Barcodes for support issues.
Result Array of the following object:

Parameter
Description
InternalOfferToken Token to identify payment.
ContentID Optional: This is the ID of the content that was bought (normally a coupon) It can be used to navigate to the right content in the appfeed.
StatusCode OK for success. Error code when not successful.
StatusMessage Optional: Blank when successful. Error details when not successful.
RejectCode Optional. A code that can be used to programatically recognize the cause of a rejection. If this field is set it means that the reservation has failed, all other values for this reservation must be disregarded.

The following values can occur:

  • Unknown
RejectMessage Optional. A human readable cause of rejection message in case a rejection occurred. Only set when RejectCode is set.

Offer tokens

The offer token will be sent from LIQUID Barcodes to the mobile app (see the section for mobile app services above). The mobile app will forward the offer token to the payment provider for items that the user wants to buy. Encrypted in the offer token are item details that are guaranteed to untampered by a compromised mobile application or any other security concerns the data may be exposed to after leaving LIQUID Barcodes before arriving at the payment provider. The offer token is only decryptable by the payment provider private key. In preparations the payment provider must create a public/private key pair and send LIQUID Barcodes the public key.

The format of the offer token is two BASE64-encoded string separated by a pipe (|) character. The parts are:

  1. An encrypted PAYLOAD-KEY, encrypted with the payment providers public key.
  2. A JSON payload (specifed below) encrypted by key PAYLOAD-KEY.

Thus, the payment providers process to access the payload will be:

  1. Split the offertoken in two pieces, separated by pipe (|): KEY-X, PAYLOAD
  2. BASE64-decode KEY-X. Decrypt (RSA-1024) it with your private key. You now have PAYLOAD-KEY.
  3. Split PAYLOAD-KEY in two pieces,  separated by pipe (|), you will get the IV (Initialization Vector) and key needed for payload decryption.
  4. BASE64-decode PAYLOAD. Decrypt (Rijndael) it with the IV and the key from PAYLOAD-KEY.
  5. JSON-deserialize the decrypted payload into model as specified below.

 

Offer token payload model:

 

Parameter
Description
Expiration Date and time this offer token expired. Make sure to reject expired offer tokens.
Item Information about the item the user selected:

Parameter
Description
ShopOfferId The unique ID for this particular offer.
PaymentProviderId Used by Liquid Barcodes to identify which payment provider is requsting us (see above).
RetailPrice The price to the consumer.
Currency Will always be the currency of the app's country (one app, one country).
Description A textual description of the shop offer.
Type Reserved for future use, will presently always be 'Shop'.
InternalOfferToken Must be forwarded to LIQUID when payment was successful in the /transactions/reserved service (see above).

 

Decrypting offer token in .NET / C#

See the following code example:

https://bitbucket.org/snippets/liquid_barcodes/7Eqkr

List of errors

All errors will contain these parameters in their body. Errors may be detected by the presence of RejectCode.

 

 

Parameter
Description
RejectCode Logically recognizable problem code.
RejectMessage English human readable error message.

Change log

Here is a list of all updates to the Coupon API:

 

Version 3.2.8
– Language is now optional parameter for IssueRequest and GetContent

Version 3.2.7
– Replaced X-Liquid-Date header with X-Liquid-Timestamp header to be in line with the other specifications. The X-Liquid-Date header
is now deprecated (but will work for until the next major revision)

version 3.2.6
– Specified standard report format for GetReport (csv)

version 3.2.4
– Changed all signature calculations to SHA-2 256 variant (MD5/SHA-1 will continue to work for a time period)

version 3.2.3
– Added better error response codes
– Changed GetReports logic to initiate a report to be generated when not found
– Removed Yearly as an option when getting reports

version 3.2.1
– Added e-mail as user reference option to IssueRequest function

version 3.2.0
– Added GetContent function, allowing to get coupons, surveys and games
– Deprecated GetCoupon as GetContent replaces the function

version 3.1.0
– Added the functionality to issue content based on what has been purchased in the virtual shop in the app

version 3.0.6
– Clarification that all implementations towards this API should be server-to-server.
– Added requirement that all implementation should implement mechanisms to prevent spamming and allowing 3rd party ‘infinite coupon generators’

Coupon Event API

 

Introduction

This is a web service that allows you to check the status on coupons and other content from Liquid Barcodes. The API offers a subscription service and after such registration, Liquid Barcodes will post update events for the specified content. This update can also include information to trigger rewards in third party systems, such as tokens, data or bonus points.

This is an extension to the Coupon API.

The purpose of this specification is to describe the mechanisms for how users of the coupon API can get callbacks on specific events in the Liquid Barcodes system. The mechanism consists of two parts

  • Registering a listener with the Liquid Barcodes system. This provides Liquid Barcodes with the URL and credentials required for us to send the events to your system in a secure manner
  • Specifications of endpoints that will receive the events and the format we will send the event information in.

Signature Debugging Tool

 

Subscribe to events

General principles

All services in this section:

  • Are hosted on https://api.barcodes.no/v3
  • Are only to be used via HTTPS
  • Require HTTP BASIC authentication. The credentials will be provided by Liquid Barcodes.
  • Require the following headers set:
Header
Description
X-Liquid-Timestamp Timestamp (format ISO-8601) when you sent the request, old request will be denied.
X-Liquid-Nonce A unqiue random value.
X-Liquid-Signature The SHA-2 256 signature of the above timestamp + nonce + your secret salt.
The secret salt will be given to you by LB.

POST /listener

Registers a listener that will receive events (see next chapter).

NOTE: Based on the authentication we identify which customer you are. You can not register a listener to any schedule ID you do not own.

 

REQUEST

Parameter
Description
BaseUrl The base URL we will send the events and where we expect to have a listener ready. HTTPS is required.
BaseUrlAuth

Authentication parameters for the BaseUrl that LB must use.

For open services (or IP filtered):

Parameter
Value
Description
Type OPEN Authentication type.

 

For BASIC HTTP authentication:

Parameter
Value
Description
Type BASIC Authentication type.
Username Username to send.
Password Password to send.
EventTypes Event types that should be sent to the listener. Array of strings.

Possible values are: Status, Usage, Rewards, Report

ScheduleIds Optional: Array of schedule IDs the listener should receive events for. If you specify no schedules the listener will receive events for all schedules you have access to.

 

The X-Liquid-Signature is calculated by X-Liquid-Timestamp + X-Liquid-Nonce + BaseUrl + BaseUrlAuth + EventTypes + SecretSalt

A successful registration will respond with a HTTP 200 - OK.

 

RESPONSE

Parameter
Description
ListenerId The ID of your listener.

DELETE /listener

 

REQUEST

Parameter
Description
ListenerId Optional: ID of the listener to unsubscribe
BaseUrl Optional: Listener BaseUrl to unsubscribe (may unsubscribe more than one).

 

The X-Liquid-Signature is calculated by X-Liquid-Timestamp + X-Liquid-Nonce + SecretSalt

A successful registration will respond with a HTTP 200 - OK.

 

RESPONSE

Parameter
Description
Unsubscribed

Array of the following objects detailing the listeners that were unsubscribed.

Parameter
Description
Id ID of the listener.
BaseUrl Base URL of the listener.
EventTypes Array of strings. Event types of the subscription.
ScheduleIds Array of subscribed schedule IDs.

GET /listeners

 

REQUEST

The service has no arguments.

The X-Liquid-Signature is calculated by X-Liquid-Timestamp + X-Liquid-Nonce + SecretSalt

A successful registration will respond with a HTTP 200 - OK.

 

RESPONSE

Parameter
Description
Listeners

Array of the following object:

Parameter
Description
Id Listener ID
BaseUrl Listener Base URL.
EventType Array of strings. Event types for the listener.
ScheduleIds Array of subscribed schedule IDs.

POST /status-request

 

REQUEST

Parameter
Description
Type Content type. Possible values are Coupon, Survey, Game.
Id Optional: ID of the content of above type you want the status for.
Code Optional: For content type Coupon we can search by code code instead of the ID.

 

NOTE: Either ID or Code must be specified for type Coupon. For the other types ID is mandatory.

The X-Liquid-Signature is calculated by X-Liquid-Timestamp + X-Liquid-Nonce + Type + SecretSalt

RESPONSE

Provided the call is well formed, the reply will always be HTTP 200 OK. The status of the content will be returned asynchronously to your subscribed listeners through the listener's callback services (see next chapter).

Callback services

The following sevices must be implemented for your listener BaseUrl. For events that you are registered to receive LB will send the response in this format to your provided URL.

We will attempt three re-tries to a listener before we will discard the message.

General principles

All requests in this section:

  • Are sent from LB to you. They they are web-hooks, requests we send to you as certain things happens in our platform.
  • Will have the following headers set:

Header
Description
X-Liquid-Timestamp When we generated the request.
X-Liquid-Nonce A unique random value.
X-Liquid-Signature The SHA-2 256 signature of the above nonce + the salt registered with the listener.

POST /status

This returns the state of the content ID (or code) that was passed to Liquid Barcodes in POST /status-request. This happens asynchronously.
Note that if Type/Id was not found we will still send this request - with the Owner/Status fields left out.

 

REQUEST

Parameter
Description
Type The type for the content. See the status-request service for possible values.
Id The ID of the content of the above type.
Code Optional: Coupon code (only set when content type was coupon).
Owner Optional: The owner of the content.
If the Type/Id was not found, this field will not be set.
Status Optional: The following sub-fields may be set, depending on content type.
If the Type/Id was not found, this field will not be set.

Coupons:

Parameter
Description
Depleted Boolean true/false. True when it's no longer possible to use content.
Uses Number of uses.
MaxUses Max allowed uses.
LastUse Optional: Timestamp (format: ISO-8601) of last usage.
Not set if not yet used.
Expired Boolean true/false. True when content expiration date has passed.

Games:

Parameter
Description
Depleted Boolean true/false. True when it's no longer possible to use content.
Uses Number of uses.
Expired Boolean true/false. True when content expiration date has passed.

Surveys:

Parameter
Description
Depleted Boolean true/false. True when it's no longer possible to use content.
Uses Number of uses.
Expired Boolean true/false. True when content expiration date has passed.

 

RESPONSE

A 200-OK response means you confirm that you have received the request. Any other status and LB will retry the same request later (max 3 retries).

 

POST /usage

The system will provide an event every time some content is used (Validated, redeemed, answered, played etc). You can only subscribe to events that are coming from the content you have access to.

 

REQUEST

Parameter
Description
Type The type for the content. See the status-request service for possible values.
Id The ID of the content of the above type.
Code Optional: Coupon code (only set when content type was coupon).
Owner The owner of the content.
Status The following sub-fields may be set, depending on content type.

Coupons:

Parameter
Description
Timestamp Event timestamp (format ISO-8601).
Store LB Store ID (when available).
Uses Number of uses.
RemainingUses Number of uses still left. When 0 no more uses can occur.
Depleted Boolean true/false. True means there are no more remaining uses, content cannot be used again.

 

Games:

Parameter
Description
Timestamp Event timestamp (format ISO-8601).
Uses Number of uses.
Depleted Boolean true/false. True means there are no more remaining uses, content cannot be used again.

 

Surveys:

Parameter
Description
Timestamp Event timestamp (format ISO-8601).
Uses Number of uses.
Depleted Boolean true/false. True means there are no more remaining uses, content cannot be used again.

 

RESPONSE

A 200-OK response means you confirm that you have received the request. Any other status and LB will retry the same request later (max 3 retries).

POST /reward

This service allows Liquid Barcodes to trigger issue of a reward in a third party system

 

REQUEST

Parameter
Description
Id LB transaction ID for this reward.
UserRef Reward this UserRef
Reward A customer specified Reward. This is text that you can set up in the LB campaign.  It could for example identify which reward to issue in your system.

 

RESPONSE

A 200-OK response means you confirm that you have received the request. Any other status and LB will retry the same request later (max 3 retries).

POST /report

 

REQUEST

Parameter Description
ReportName The name of the report as ordered
ReportPeriod The period for the report. Currently the following options are supported: 'Day', 'Week', 'Month', 'Quarter'.
Date The startdate for the report.
ReportLink Link to the requested report

 

RESPONSE

A 200-OK response means you confirm that you have received the request. Any other status and LB will retry the same request later (max 3 retries).

Change log

Here is a list of all updates to the Coupon Event API:

 

version 1.0.4
– Updated an event type

version 1.0.3
– Changed all signature calculations to SHA-2 256 variant (MD5/SHA-1 will continue to work for a time period)

version 1.0.2
– Listener functions now implemented
– Added callback function for listening on reports being generated

version 1.0.1
– Minor text changes

POS Validation API

 

Introduction

 

The POS API allows retailers to automatically redeem coupons through their POS.

General principles

Background

 

Through the POS integration, retailer can redeem coupon codes from Liquid Barcodes. The process is a two step process. Step 1 is Reserve, Step 2 is Validate or Cancel.

 

 

Nomenclature

 

In order to maintain consistency throughout the description the following terms have been used. To avoid ambiguity they are defined here:

 

Name
Description
Barcode Graphical, scannable / machine-readable, representation of code (including prefix).
Cancellation The cancellation of a reservation whose conditions were not met.
Code A code given to the customer representing an offer given to the same customer.
Coupon A coupon (image or text) containing a code (see above).
Internal reference ID An unique reference that uniquely identifies this transaction from the perspective of the POS. If more than one parameter is used, the field takes the format “parameter1:parameter2:parameter3
LIQUID A short hand reference to Liquid Barcodes and this API.
LiquidReference An unique reference used by LIQUID to keep track of the transaction.
Normal reservation The normal mode for reservations. One or more codes are specified, which are then reserved.
One-Scan A special reservation mode where all codes owned by a user are reserved. Can be initiated either by specifying the user or by specifying a code owned by the user.
Prefix The code (see above) may need a prefix, for example to route the reservation to LIQUID Barcodes’ systems.
Rebate Handling Tender Exchange/ Cash Equivalent /Rebate
Redemptions See validation below.
Reservation Singular, unique offer that corresponds to the particular use of a code (see above).
User A person that is the intended recipient of (a) coupon(s)
UserReference/UserRef A unique reference to the User that can be used to uniquely identify the User. Most commonly their phone number (MSN), but can also be membership IDs or other unique identifiers
Validation The confirmation of a reservation whose conditions were met.

Coupon elements

 

The coupon is built up from certain elements:

The main elements of a coupon are:

  • Code, this is the actual code that carries the real value of the discount. There is no limitation on the length of the code, nor is the code limited to digits only. However in practical implementations this code is 8 digits. This parameter is also known as UniqueCode
  • Barcode, this a representation of the code in a form that is easy to scan. In order for the POS to identify the barcode as originating with Liquid Barcodes the content of the Barcode normally takes a form of ‘Prefix + Code’. The prefix part of the configuration for each retailer. The barcode is constructed in one of three ways (of which the first is the predominant structure)
  • Prefix + UniqueCode. In total 12 digits.
  • Prefix + UniqueCode + Control digit. This is only used when the barcode has to be of type EAN-13, where the last digit is a control digit.
  • Prefix + ’01’ + CampaignCode + ’21’ + UniqueCode.

 

Process for validating coupons

 

The basic concept is that when a coupon/code is scanned/entered manually the system returns the corresponding reservation with conditions. This reservation is unique and subsequent uses of the same code/coupon will result in a new reservation with conditions that may or may not be identical to the first. Once the sale is completed, the reservation is either validated (the conditions have been met) or the reservation is cancelled/freed (the reservation’s conditions have NOT been met).

We use the term coupon or code as the representation of the offer to the consumer, and reservation as the singular, unique offer that corresponds to a particular use of the coupon. A coupon/code may in other words trigger multiple reservations with separate conditions.

The process of validation is done in two stages. Once the coupon is scanned or the coupon code is manually entered at the POS, a reservation request is sent from the POS to LIQUID (RESERVE function). Upon receipt of the RESERVE message LIQUID will respond with an acknowledgement message and this message may be positive (the coupon exists and can be used) or negative (the coupon doesn’t exist, is not valid, or has already been used). If the RESERVE response is negative an appropriate message to the cashier/consumer should be displayed, according to the error types described in this document.

A positive RESERVE response, called a reservation, will also contain conditions that need to be fulfilled before the rebate can be given to the consumer. Typical conditions are what products need to be on the receipt, the size and type of the rebate, a minimum total sale etc. A successful reservation will mark the coupon as reserved in LIQUIDs system, and this particular use of the coupon is locked until the reservation is either cancelled or validated. If the coupon can be used more than once, each use requires a separate reservation request, as the conditions for the rebate may change for each use of the coupon (an example would be a coupon that gives 5 % rebate for the first use, 10 % for the second, 15 % for the third, etc…). Once the sum of unconfirmed reservations and previous validations of a coupon/code equals the maximum number of validations it will no longer be possible to reserve the same code, unless one or more of the reservations are cancelled.

When the sale has been concluded, the POS has to determine whether the conditions for the reservation has been met (i.e. the required products are present on the receipt). When receiving payment from the consumer the POS must send a final confirmation to LIQUID containing whether  the consumer received the rebate. This is done through the validation request (VALIDATE function), as a confirmation or a cancellation. LIQUID will respond by sending VALIDATE response to confirm that it has received the validation. If no VALIDATE response is received the POS should retry at least 3 times.

If the rebate/coupon is removed from the receipt or the conditions have not been met, the POS should send a VALIDATE message and indicate that this reservation was cancelled. This will free the code for later use.

Cancelling reservations and clean up

Since coupons can be multi-use and each reservation can have different conditions the sequence of which reservations takes precedence is important. For reservations that belongs to the same coupon/code the reservations should be cancelled in the order of the most recent reservation first. As an illustration, a coupon has been reserved three times that gives 5, 10, 15 % rebate respectively on product A and 3 product A is present on the receipt. There are now two situations that needs to be handled properly:

  • The cashier removes one of the product As from the receipt (irrespective of which of the three A’s is cancelled). In this case the last reservation (15 % discount) no longer holds, but both 5 and 10 % discount is still valid
  • The cashier removes one of the reservations themselves (if made possible by the POS implementation). Regardless of which reservation that is removed, the most recent reservation should be cancelled (15 % discount)

 

System clean-up and parking the receipt

As a fail-safe in case the POS is unable to validate a reservation (by validating or cancelling), to prevent reservations from lasting indefinitely and to prevent that consumer is unable to use the coupon at a later stage, all reservations are automatically cleaned up 15 minutes after the reservation is made. If this occurs it is no longer possible to complete the validation (by validating or cancelling).

In the case where the receipt is intentionally parked/paused one risks that the clean-up happens while it’s parked. There are multiple alternative ways to handle this. The preferred option is the first one, however, depending on POS architecture and other factors, this may not always be ideal and the alternative implementation may be a better solution.

  1. Cancel all reservations when unparking the receipt and immediately reserve them again.
    If the coupon has been used on another order in the mean time the reservation will fail, if not the reservation will go through.
  2. Trying to make it before time-out.
    When the receipt is unparked the reservations can be in the following states and the POS will have to consider what to do with them.

    • Before the reservations time-out. The rebate is given and the validations will still go through, however, the time before validations must happen is reduced by the time the receipt was parked.
    • After the reservations time-out. When finalizing the purchase the validations will fail, and this should be handled by either replaying reservations. Alternatively, allowing the user scan his/her coupons again before finalizing the sale.
  3. Cancel all reservations when parking the receipt.
    The user must be notified that the coupons will have to be scanned again.

Additional receipts

 

This API allows for additional receipts being printed which contains additional coupons. Note that these additional coupons will be issued on the basis of the initial transaction, and can hence not be used in the original transaction. As such this is a mechanism to get people to revisit your stores. There are two ways to invoke additional receipts and only one should be used per transaction:

  • LIQUID Barcodes will add additional receipts to the transaction as a field on the VALIDATE response.This implies that there has been at least one coupon present during the transaction (note that the coupon may not give a discount in itself, but represent a membership card). The rules for which offer(s) to trigger for the additional coupons are then set up in LIQUID Barcodes system entirely, and conditions can span several purchases.
  • The POS will during the finishing phase of the transaction query LIQUID Barcodes with the complete receipt for the transaction and an additional receipt may be returned based on either the total value in the purchase or which individual products were present. Note that this may issue coupon to any customer that has not already used a LIQUID Barcodes coupon in the transaction. To activate this functionality the POS needs to call the Receipt function call that is detailed below. If the user has used some LIQUID Barcodes coupon on the transaction, this function should not be called.

It should be noted that based on the configuration of the campaigns, and what information is available for the individual consumer, a receipt coupon may be distributed to the consumer through a different distribution channel. E.g. If the mobile number of the consumer is known to LIQUID Barcodes the system will distribute the coupon on SMS directly to the consumer. If the mobile number is not known the same coupon would be returned as an extra receipt to be printed by the receipt printer. The configuration of distribution channels is a property of the LIQUID Barcodes system.

Receipt text format

 

The format is a minimalist XML format. There is no XML-header used in the format and there is no XSD available.
Receipt texts are only used in the context of the Validation API and as such the enclosing HTTP response headers define the character set for this content.

 

Supported tags

<RECEIPTS>

This is the container tag for all additional receipts. There will be only one of this tag.

<RECEIPT>

This is the container tag for one additional receipt.

Supported attributes (default values underlined):

  • reservationid=” X 
    If this receipt was created from a validation, this value references the reservation ID for the reservation+validation that triggered it.
    Optional attribute.
<BARCODE>

A barcode to add to the receipt. The value of the barcode is given as content for the tag.

Supported attributes (default values underlined):

  • type=” datamatrix | ean13 
    Format of the barcode. Required attribute.
<IMAGE>

An image to add to the receipt. The binary data of the image is given as content for the tag. Any whitespace characters should be removed from the content before decoding, as the content may have been chunked.

  • format=” image/png 
    The image format used in the enclosed binary data. Required attribute.
    Currently the only supported format is image/png.
  • encoding=” base64 
    The encoding used on the enclosed binary data. Required attribute.
    Currently the only supported encoding is base64.
<TEXT>

A text paragraph, optionally formatted (see level four tags), to add to the receipt. All text content should be trimmed for any leading/trailing whitespaces. Multiple consequtive whitespaces should be treated as one whitespace. Linebreaks should be treated as spaces, as linebreaks are explicitly defines by BR tags.

Supported attributes (default values underlined):

  • align=” left | center | right 
    Text alignment. Optional attribute.
  • color=” #rrggbb ”
    Text color in hexadecimal red (rr), green (gg) and blue (bb) components. Optional attribute.
<B> for bold

The content of this tag should be formatted as bold text.

<I> for italic

The content of this tag should be formatted as italic text.

<SMALLER>

The content of this tag should be formatted slightly smaller than other text.

<BIGGER>

The content of this tag should be formatted slightly bigger than other text.

<BR>

Line break. Whitespaces before and after the linebreak should be trimmed.

<COLOR>

Supported attributes (default values underlined):

  • color=” #rrggbb ”
    Text color in hexadecimal red (rr), green (gg) and blue (bb) components. Required attribute.

PoS Bandwidth and Latency Requirements

 

The amount of data transmitted through the API is quite limited with a typical payload of less than 1 kB (but it can be larger). In theory it means that the data can be transmitted over very low bandwidth networks. However the limiting factor is typically not the bandwidth but the latency as the network latency can significantly increase the time the consumer has to wait by the PoS for the transaction to finish. Additionally, as this service requires the PoS to be online at all times, the stability of the open connection is very important for the consumer experience at the PoS. A model for the time constraints related to processing of a reserve can be expressed as:

TReserve = TScan + TNetworkLatency + TTransfer + TLiquidBarcodesProcessing + TNetworkLatency + TTransfer + TPoSProcessing

= TScan + 2 * TNetworkLatency + 2 * TTransfer + TLiquidBarcodesProcessing + TPoSProcessing

where

  • TScan is the time taken from the coupon has been scanned to the request from the PoS to Liquid Barcodes is initiated
  • TNetworkLatency is the latency of the network in question. This may vary significantly depending on the network configuration, and also includes the routing through the internet to the Liquid Barcodes servers
  • TTransfer is the actual transfer speed of the data packet. Given the small size of the payload this component would be ~150 ms for a 1kB packet over a 64kbit/s ISDN
  • TLiquidBarcodesProcessing is the time it takes for Liquid Barcodes to process the incoming request and send the response. Typically this is processed in 100 to 300 ms
  • TPoSProcessing is the time the PoS requires to process the incoming conditions from LB and align with the current transaction at the PoS

Additionally there is a second Validate function call that happens when you close the bill on the PoS which has the following time constraints

TValidate = TClosingBill + TNetworkLatency + TTransfer + TLiquidBarcodesProcessing + TNetworkLatency + TTransfer + TPoSProcessing

= TClosingBill + 2 * TNetworkLatency + 2 * TTransfer + TLiquidBarcodesProcessing + TPoSProcessing

where

  • TClosingBill is the time taken from the cashier closes the sale until the request to Liquid Barcodes is initiated
  • TNetworkLatency is the latency of the network in question. This may vary significantly depending on the network configuration, and also includes the routing through the internet to the Liquid Barcodes servers
  • TTransfer is the actual transferspeed of the data packet. Given the small size of the payload this component would be ~150 ms for a 1kB packet over a 64kbit/s ISDN
  • TLiquidBarcodesProcessing is the time it takes for Liquid Barcodes to process the incoming request and send the response. Typically this is processed in 100 to 300 ms
  • TPoSProcessing is the time the PoS requires to process the incoming conditions from LB and align with the current transaction at the PoS. Given that there is very little to process at this stage, the PoSProcessing step should be fairly insignificant.

Our recommendation is to have sufficient available bandwidth in order to minimise the latency. In the end the service will work with high latency too, but the wait for the consumer will at some point be unacceptable. We do however recommend to have a 500 kbit/s line from PoS to the internet (provided that the line is shared with other services), but as a minimum our service can operate reasonably well on a dedicated symmetric 64kbits/s line (that is always connected)

General notes for using the services

 

The API is available through a secure web service exposed at https://validator.api.barcodes.no/v3 . The client can expect a signed, valid SSL certificate for this endpoint.

Some standard HTTP response statuses are used to indicate success or failure. See Responses section below.

Authentication, timestamp and signatures are required for all services and are submitted as headers. See Requests section below.

All dates and times must be formatted as a ISO-8601 timestamp, for example 2014-03-06T13:11:04+03:00.

The unique coupon codes should not be added to the printed receipts, as it would allow a third party that gets access to the receipt to use another person’s coupons.

 

REQUESTS

All services require:

  • Authentication via the HTTP header Authorization. We use the BASIC authentication mechanism. Username and password are provided by LIQUID.
  • A timestamp via the HTTP header X-Liquid-Timestamp. It should be set to the current time when the client sends a request and must be formatted as a ISO-8601 timestamp, for example 2014-03-06T13:11:04+03:00.
    The services will reject any request where the time deviates more than 10 minutes from our current time.
  • A signature via the HTTP header X-Liquid-Signature. See the section below on Calculation of the signature. 
    The services will reject any request where the signature cannot be verified.

 

RESPONSES

The HTTP response code will identify the outcome of any request.

  • 200 (success): The request was successfull.
  • 400 (bad request): A value in the request was considered wrong and caused the processing to stop. One typical value is the signature.
  • 401 (unauthorized): There was a authentication problem (username and password is provided by LIQUID, contact support).
  • 500 (internal server error): There was an unexpected problem (contact support).

Note that these codes are response-level status codes (as in one response, as a whole). In other words a 200 / success response may well contain rejected reservations / validations / cancellations. These can be identified by inspecting the nested RejectCode and RejectMessage fields. Furthermore a non-200 / unsuccessfull response code means the whole request has been rejected, with the exception of 500-errors which means something unexpected has occurred and the state is uncertain.

Unless another format is specified in the Accept header of the request, the format of the response body is JSON. The format of the response body can always be found in the Content-Typeheader.

Signature

 

In addition to authentication the services use a signature to further validate the customer and the authenticity of the request.

The signature is calculated from the following parts concatenated to a string (without any separator between the parts):

  • The exact value of the X-Liquid-Timestamp header
  • The content of the request (which fields and their order is specified in each services specification below).
  • The secret salt provided to you by LIQUID.

The correct signature is the hexadecimal upper-cased SHA1 hash value from this content.

Example

Given the following:

  • The customer salt is 123SALT123.
  • The username is demouser.
  • The password is demopassword.
  • We want to reserve the UniqueCode 78907890.

The following is an example of a valid Reserve request:

 

POST https://validator.api.barcodes.no/v3/reserve HTTP/1.1
Accept: application/json
X-Liquid-Timestamp: 2015-02-10T22:53:44Z
X-Liquid-Signature: 25EC3D52BE0E728D4BF50A452B98E3E393C610AD
Content-Type: application/json
Host: validator.api.barcodes.no:443
Authorization: Basic ZGVtb3VzZXI6ZGVtb3Bhc3N3b3Jk

{
  "RetryCounter":0,
  "StoreRef":"MYSTORE001",
  "PosRef":"MYPOS002",
  "OperatorRef":"MYOPER003",
  "TransRef":"MYTRANS004",
  "InternalPosRef":"MYINTPOS005",
  "UserRef":"MYUSER006",
  "Codes":[
    {
      "UniqueCode":"12341234",
      "CampaignCode":"9876543210123" 
    }
  ]
}

Notice:

  • Authorization header for basic HTTP auth.
    BASE64(“demouser:demopassword”) =  ZGVtb3VzZXI6ZGVtb3Bhc3N3b3Jk
  • X-Liquid-Timestamp header format in ISO-8601 format.
  • X-Liquid-Signature see detailed calculation explained below.

Looking at the Service specification in the next chapter you can see that signature source for the Reserve service is made concatenating the following data:

  • StoreRef + PosRef + OperatorRef + TransRef + InternalPosRef
  • All Codes items concatenated (no separator). Each item consisting of the following values:
    • UniqueCode
    • CampaignCode
  • UserRef + RetryCounter

Which yields the same signature you can see in the requests X-Liquid-Signature:

modelsource = "MYSTORE001" + "MYPOS002" + "MYOPER003" + "MYTRANS004" + "MYINTPOS005" + "12341234" + "9876543210123" + "MYUSER006" + "0"
// modelsource is "MYSTORE001MYPOS002MYOPER003MYTRANS004MYINTPOS005123412349876543210123MYUSER0060"
 
source = "2015-02-10T22:53:44Z" + modelsource + "123SALT123"
// source is "2015-02-10T22:53:44ZMYSTORE001MYPOS002MYOPER003MYTRANS004MYINTPOS005123412349876543210123MYUSER0060123SALT123"
 
signature = UPPERCASE(HEX(SHA1(UTF8(source)))) 
// signature is "767778229A2A91E63BADA993AB79BE90F69E7AA9"

Disclaimer

 

This document describes the process flow and protocol for validating coupons issued by LIQUID Barcodes on behalf of the stores. In order to utilize this interface there must be a commercial agreement with LIQUID Barcodes in place, and a technical verification that the implementation has been implemented correctly. In all circumstances the intellectual property rights (IPR) of the interface resides with LIQUID Barcodes. LIQUID Barcodes reserves the right to change this interface at any moment. Any implementation that utilizes this interface is the sole responsibility of the implementor, and under no circumstances should the issuing of this document be construed to signify that LIQUID Barcodes will participate with the implementation, testing, verification of the implementation, unless otherwise agreed.

Standard POS Integration

 

 

Introduction

Liquid Barcodes POS Integration ensures quick and efficient customer experience in store. The member discount calculation is performed by Liquid Barcodes. This simplifies the POS integration.

 

 

  • Customer identifies once in store.
  • When all products have been added to the transaction, POS sends customer identification and list of products to Liquid Barcodes. Liquid Barcodes applies personal discounts. POS receives list of products and updated prices.
  • When customer has paid and transaction has been closed, POS sends validation request to Liquid Barcodes. If customer wants to add products or on unsuccessful payment, POS sends cancel request to Liquid Barcodes.

 

The Standard POS integration uses the Applicator services – Reserve and Validate.

Applicator service – Reserve

 

API to be completed 2019.

Applicator service – Validate

 

API to be completed 2019.

Alternative POS integration methods

Integration alternatives

Liquid Barcodes offers multiple alternative POS integration methods.

 

In store handling

  • Handle one coupon at a time
  • Multi-use
  • Identify once per transaction

 

How to communciate the offer conditions to the POS

  • Promotion ID
  • Conditions

 

The options are summarized and described in this table:

 

Identify once

 

Customer only registers once per transaction.

The API allows for the usage of unique User IDs instead of scanning individual coupons. The typical use case is that the consumer is identified by his membership number or registered payment method (eg. credit card) and will receive all the offers he is entitled to without having to scan multiple coupons. Note that the process of identifying the user ID from credit cards and translating from the credit card details to the unique user reference is not handled by LIQUID.

Once the user is identified, the POS can send a RESERVE request to LIQUID with the unique User ID in place of a coupon code. A successful reservation will return the collected results of a reservation for all of the users available coupons. That is, it will return the first available reservation for each coupon that the user is eligible for. Once the conditions for a reservation is met (and the corresponding coupon can be used several times) the POS must automatically fetch the next reservation for that coupon (see multi-use above).

Once the sale is completed and the products are paid for, all the reservations can be validated/cancelled in a single VALIDATE request.

Multi-use

 

This is a hybrid between the “One coupon at a time” and “Identify once” POS integration methods.

 

When scanning multiuse coupons, such as loyalty cards, POS automatically makes a new reservation when the offer conditions matches the product(s) on the receipt.

 

One attribute of a coupon is that it may be used more than once, e.g. three times, 5 times or unlimited numbers of times. The conditions for the rebate may differ for each subsequent reservation. To prevent that the consumer has to scan the coupon multiple times to use it multiple times on the same receipt, the POS should automatically reserve the coupon/code given that certain conditions are met.

When the conditions for a reservation is met, the coupon has more remaining validations and the coupon can be used more than once per sale, the POS should automatically reserve the coupon again and receive a new set of conditions. An example would be a coupon that can be used 3 times, and give a rebate when buying a particular product (A), The rebate given is 5 % discount first usage, 10 % discount second usage, and 15 % discount on the third and final usage. A consumer then scans the coupon at the POS (this initiates the first reservation), and adds product B, C and D on the receipt (which will not meet the conditions for the reservation). The consumer then adds product A, and the conditions for the first reservation is met. As the coupon can be used multiple times on the same sale and have remaining uses, the POS automatically reserves the coupon a second time and receives the second set of conditions. The consumer adds another product A, and the conditions for the second use has also been met, which triggers the third reservation. When the consumer adds the third product A the conditions for the third reservation is met, but as there are no further uses left the POS doesn’t reserve a fourth time.

In the example above, if at any time one of the product A’s is removed from the receipt, the rebate associated with the most recent reservation must be undone (the 15 % discount)

To simplify the process, all outstanding reservations can be validated/cancelled in a single VALIDATE request.

One coupon at a time

 

Shopper must register each coupon she wants to use one time per usage. Say for example she has bought two loyalty card products. She must scan her loyalty card two times to get two stamps on the loyalty card.

 

On each scan, Liquid Barcodes makes a reservation on the coupon code and replies with correct rebate conditions.

 

When transaction is complete, POS must validate the reservations that have been used.

 

If shopper scans too many times, POS must automatically cancel unused reservations.

 

This is a basic POS integration. It is easier to implement in the POS than the other integrations. The disadvantage is that it takes more time in store.

 

 

 

Offers based on Promotion ID

On reservation, Liquid Barcodes replies with Promotion IDs for the shopper’s personal offers.

 

The Promotion IDs are discount triggers that have been created in the POS before campaign start.

 

POS only applies Promomtion ID from each reservation once. To obtain additional Promotion IDs, new reservation must be made.

 

The advantage of using Promotion IDs is that discounts can be determined using POS existing rebate engine. The disadvantage is that the marketeer must maintain two systems – the coupon campaigns and the Promotion IDs.

 

The Promomtion IDs will be sent to POS using the ExternalParamater field in the Reservation response.

Offers based on Conditions

On reservation, Liquid Barcodes replies with rebate conditions for the shopper’s personal offers.

 

The rebate conditions define in detail the requirements for this particular rebate to apply and the value of the rebate.

 

POS only applies Conditions from each reservation once. To obtain additional Conditions, new reservation must be made.

 

The advantage of using Conditions is that the marketeer only needs to maintain one system. The disadvantage is that discounts must be calculated using a custom rebate engine in the POS.

 

The Conditions will be sent to POS using the Conditions field in the Reservation response.

Reserve

 

POST  https://validator.api.barcodes.no/v3/reserve

 

REQUEST

Fieldname Title Description
StoreRef Store reference The store reference is the unique identifier for the store of that retailer. Will be allocated by LIQUID, and will only change if the cash register is physically moved to another location.
PosRef Cash register reference The reference of the particular POS used in the transaction. If used this ID is at the discretion of the store. This ID will NOT change upon a change of owner of the store
OperatorRef Cashier reference Optional. An anonymous identifier for the cashier using the cash register. If used this ID is at the discretion of the store.
TransRef Transaction reference Unique identifier for the particular transaction on the cash register. Has the same value across the whole receipt, and is unique across all stores. The TransRef uniquely identifies one and only one receipt in all the transactions of the retailer.
LegalEntity Legal entity Optional. An identifier that identifies the legal entity that owns the store. This will change upon a change of owner of the store. If not blank the value in this field will appear in the validation report for this validation.
InternalPosRef Internal reference ID Optional. Parameter that maps the transaction to the internal cash register reference ID. If more than one parameter is used, the field takes the format “parameter1:parameter2:parameter3” May optionally be left blank.
RetryCounter Retry counter Initially this value is always 0. In case the POS needs to retry the request the value should be increased by 1 per attempt.

It is used to handle network issues or other issues where the POS does not know whether a request was successfully submitted.

UserRef Unique user reference Optional. For normal reservation mode this field should be blank. To enter one-scan mode this can be set to:

  • The unique reference to the user. In this mode Codes must be empty or the reserve will proceed as a normal reservation.
  • The special trigger value [ONESCAN-RESOLVED-FROM-CODE] . In this mode Codes must contain exactly 1 entry with UniqueCode set. A one-scan will be performed for the owner of this code.
Codes Array of codes to reserve. This array should be empty if UserRef is present
CampaignCode Campaign code Optional. Campaign code in the barcode of the coupon. If UniqueCode is manually entered this field is not used.
UniqueCode Unique coupon code If the coupon code is manually entered this field contains the printed digits below the barcode.
BalanceOffset Optional. Requested giftcard balance change. Negative amount means balance deduction. Positive amount means balance increase / top-up.
For giftcard reservations that do not specify a value here 0 is used.
Position Optional. An attempt to acquire geographical location.
Should be set whenever an attempt to acquire location was made. In this object you must set either Position or ErrorCode+Error.
Position Optional. Must be set when the attempt to acquire geographical location succeeded.
The position will be used to attempt identification of which store performed the reservation.
Position is given as decimal degrees (DD). Conversion from sexagesimal (DMS): With degrees, add minutes as /60 fractions, add seconds as /3600 fractions.
Longitude Longitude / meridian. Range from -180.0 (180 degrees west) to 180.0 degrees (180 degrees east).
Latitude Latitude / parallel. Range from -90.0 (south pole) to 90.0 degrees (north pole).
Accuracy Optional. The accuracy for the position in meters.
Altitude Optional. Altitude in meters, relative to sea level.
AltitudeAccuracy Optional. The accuracy for the altitude in meters.
Speed Optional. Current velocity of the device in meters per second.
Heading Optional. Current heading in degrees of clockwise deviation from heading true north (which means that 0, 90, 180, 270 degrees is north, east, south and west, respectively).
ErrorCode Optional. Must be set when the attempt to acquire geographical location failed.
Error classification. One of: PermissionDenied, Unavailable, Timeout, NotSupported, Unknown.
Error Optional. Must be set when the attempt to acquire geographical location failed.
Error message / details. May be a blank string if there are no further details that ErrorCode.

 

Signature

The signature source consists of the common header/salt data (see Calculation of the signature) and the following concatenated fields from this service:

  • StoreRef + PosRef + OperatorRef + TransRef + LegalEntity + InternalPosRef
  • All Codes items concatenated (no separator). Each item consisting of the following values:
    • UniqueCode
    • CampaignCode
  • UserRef + RetryCounter

 

RESPONSE

 

Fieldname Title Description
LiquidLogRef Log reference A reference to LIQUIDs internal logs.
Reservations Array of reservation
ReservationId Reservation reference A reference to this reservation. It will be formatted either as a number or a GUID (i.e. it should always be treated as a string).
This value is the relation between reservation and validation / cancellation (see the Validate service).
UniqueCode Unique coupon code The reserved unique coupon code.
CampaignCode Campaign code Only present if CampaignCode was used in Reserve request.
Timestamp Reservation timestamp The date and time when the reservation was completed.
Campaign
Id Campaign ID The ID of the campaign associated with the unique code.
Description Campaign description Optional: Short description of the campaign to be displayed in the POS and/or printed on the recipt.
Type Campaign Type The campaign type. Currently the only values in use are “Rebate”, “Giftcard”.
Start Campaign Start Timestamp for campaign start. This is the earliest possible time to reserve coupons for this campaign. The timestamp should be used only for informational purposes, not to decline a reservation.
End Campaign End Timestamp for campaign end. This is the latest possible time to reserve coupons for this campaign. The timestamp should be used only for informational purposes, not to decline a reservation.
CouponExpires Coupon expiry timestamp Timestamp for last possible reservation of this coupon. This value can not be later than Campaign.End.
Rebate Optional but either Rebate, Tender or both must be set.
Type Rebate type Possible values are:

  • CurrencyValue for monetary value
  • Percentage for percentage value
  • Units for valueless unit
  • FixedPrice for when rebate is calculated from the price at POS

If this field is FixedPrice then some products to rebate will be specified in the ProductGroups.

Value Rebate value The value of the rebate, see related field Rebate.Type. This field may be zero. Also the value of this field may be negative, in this case the consumer is not getting a rebate, but have to pay for the use of the coupon. Negative rebate is primarily used for prepaid/top-up cards, where the first usage of coupon allows the user to buy x rebated products for later.
MinimumValue Minimum rebate value Optional. Minimum value of the total rebate in the case where the rebate value is undetermined.
MaximumValue Maximum rebate value Optional. Maximum value of the total rebate in the case where the rebate value is undetermined. This occurs when the product in question has different sale price in the different shops where the coupon can be redeemed
Tender Optional but either Rebate, Tender or both must be set.
Type Tender type Possible values are:

  • CurrencyValue for monetary value
  • Percentage for percentage value (not yet supported).
Value Tender value The value of the tender, see related field Tender.Type. This field may be zero. Also the value of this field may be negative, in this case the consumer is not getting a rebate, but have to pay for the use of the coupon. Negative rebate is primarily used for prepaid/top-up cards, where the first usage of coupon allows the user to buy x rebated products for later. This field may have a value in combination with Rebate.

If the campaign type is of type CashCard this value represents the amount of the cashcard that has been reserved

 

RemainingRedemptions Number of remaining redemptions Number of remaining redemptions excluding this transaction. A value of zero means that there are no remaining redemptions for this coupon (except this one). A value of ‘-1’ means that there are no limits to the number of remaining redemptions.
ExtParam External parameter Optional. A list of parameter names and values that can be used by the cash register. An example would be to indicate the PLU to be inserted as a result of an redemption.
ReceiptText Receipt text Optional. Parameter that the POS can choose to print on the receipt for each reservation.
Giftcard Optional. Giftcard specific fields. Only supplied when Campaign.Type is Giftcard.
NewBalance The current balance of the giftcard after Reserve.Codes.BalanceOffset has been applied. The actual balance offset that was applied is available in Tender.Value.
MaxBalanceOffset This is the maximum value that is permitted to top-up this giftcard with (i.e. maximum Reserve.Codes.BalanceOffset). If value = 0 or parameter is not present then it is not allowed to top-up this giftcard.
RejectCode Per reservation reject code Optional. A code that can be used to programatically recognize the cause of a rejection. If this field is set it means that the reservation has failed, all other values for this reservation must be disregarded.

The following values can occur:

  • CustomerMismatch, the requested UniqueCode belongs to a campaign that is not associated with the authenticated user.
  • CampaignInactive, the requested UniqueCode belongs to a campaign that is no longer / not yet active.
  • CampaignOncePerSaleOnly, the campaign setup demands that the UniqueCode can only be used once per receipt and this requirement was not fulfilled.
  • ReservationCountTooHigh, too many unvalidated+uncancelled reservations exist for this UniqueCode.
  • ScheduleInactive, the requested UniqueCode belongs to a campaign that is no longer / not yet active.
  • ScheduleStoreMismatch, the UniqueCode was issued for use in a specific store, this requirement was not fulfilled.
  • ScheduleNoRemainingValidations, the campaign has a limited amount of validations and there are no validations left.
  • CodeInactive, the requested UniqueCode has expired.
  • CodeAlreadyUsed, the requested UniqueCode only allows one validation and is already validated.
  • CodeNotFound, the requested UniqueCode is invalid.
  • CodeDepleted, the requested UniqueCode has already been used the maximum number of allowed times
  • DailyValidationsExceeded, the code has reached or exceeded the maximum number of validations per day.
  • Blocked, the code or campaign has been blocked. Used when phasing out a campaign, for example.
RejectMessage Per reservation reject message Optional. A human readable cause of rejection message in case a rejection occurred. Only set when RejectCode is set.
RejectCode Reject code Optional. A code that can be used to programatically recognize the cause of a rejection.

The following values can occur:

  • OnescanResolveInvalidCode, the code specified for resolving a user was not usable. More details will be given in the reject message.
RejectMessage Reject message Optional. A human readable cause of rejection message in case a rejection occurred. Only set when RejectCode is set.

Validate

 

This is the second part of the validation process. This is call is initiated in the following circumstances:

  • The conditions for the reservation has been met and the customer is about to be given his rebate. This call is initiated after the customer has paid, but before the transaction has been completed.
  • The conditions for the reservation have not been met so the reservation must be released.
  • The transaction was aborted by cashier or customer so the reservation must be released.

 

POST https://validator.api.barcodes.no/v3/validate

REQUEST

 

 

Fieldname Title Description
Validations List of confirmed / approved validations.
ReservationId Reservation reference A reference to this reservation. It will be formatted either as a number or a GUID (i.e. it should always be treated as a string).
This value is the relation between reservation and validation / cancellation (see the Reserve service).
RebateValue Rebate value This is the actual rebate that was given. Should be the monetary value (not percentage). If the rebate type is percentage this value will vary depending on the basket of goods to rebate. If the rebate type is units this value is the number of units given. Should not include the TenderValue.
TenderValue Tender value This is the actual tender that was given. Should be the monetary value (not percentage). Should not include the RebateValue.
Cancellations
ReservationId Reservation reference A reference to this reservation. It will be formatted either as a number or a GUID (i.e. it should always be treated as a string).
This value is the releation between reservation and validation / cancellation (see the Reserve service).
TotalValue Total value The gross total of the receipt (i.e. the total before the deduction of the above rebate/tender).
OptParams Additional data Optional. A list of parameter names and values that can be set by the cash register. This field can be used to further detail the transaction.
RetryCount Retry counter Initially this value is always 0. In case the POS needs to retry the request the value should be increased by 1 per attempt.
It is used to handle network issues or other issues where the POS does not know whether a request was successfully submitted.
Receipt
Format Receipt format, always use Liquid/1.0 for this field. The format is detailed below
Receipt Receipt

Optional. A JSON representation of the whole receipt for the complete transaction, including the unique ReceiptID, EAN codes, Product price, rebate values, total sum etc.

The JSON should take the following format:


 Expand source

Note: The JSON code must be escaped so that the Receipt field is just a regular string.

TransRef Transaction reference Optional: Unique identifier for the particular transaction on the cash register. Has the same value across the whole receipt, and is unique across all stores. The TransRef uniquely identifies one and only one receipt in all the transactions of the retailer.The TransRef should only be used in the Validate call if for some reason the final receipt ID is not available before the POS ends the transaction. In this case the POS should use a temporary TransRef for all reservations in this transaction. If you also send the receipt in this transaction, the TransRef value should be identical to the ReceiptId in the Receipt block.

 

Signature

The signature source consists of the common header/salt data (see Calculation of the signature) and the following concatenated fields from this service:

  • RetryCount
  • All Validations items concatenated (no separator). Each item consisting of the following values:

    • ReservationId + RebateValue + TenderValue
  • All Cancellations items concatenated (no separator). Each item consisting of the following values:
    • ReservationId
  • TotalValue
  • Format
  • Receipt
  • All OptParams items concatenated (no separator between key/value, no separator between items).

 

RESPONSE

 

 

Fieldname Title Description
LiquidLogRef Log reference A reference to LIQUIDs internal logs.
Results
ReservationId Reservation reference A reference to the submitted validation or cancellation with the same ReservationId.
Receipts Receipts Information / coupons may be provided for printing on the receipt. See Receipt format.
RejectCode Reject code Optional .A code that can be used to programatically recognize the cause of a rejection. If this field is set it means that the validation / cancellation has failed, all other values for this validation / cancellation must be disregarded.

The following values can occurr:

  • ReservationNotFound, the requested ReservationId was not found. Either the reserve did not complete, or the reservation has timed out.
RejectMessage Reject message Optional. A human readable cause of rejection message in case an error occurred. Only set when RejectCode is set.
JSON

Test code