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.
In order to ease the use of this API, a Postman collection can be downloaded here.
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 + an API key unique to the customer. It is important to make efforts to obfuscate this key in the app implementation.
Let's say we have agreed upon the API key "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.
Example (pseudo) service call:
{
"DateTimeHeader": "2014-03-07T11:07:21+01:00"
"parameter_a": "abcd",
"parameter_b": "1234",
"signature": "1aaade12efceba0f9ddda4a94bce59a6"
}
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.
Liquid Barcodes requires external app developers (2nd or 3rd party) to follow guidelines for handling our API key. Technical instructions will be sent directly to the app developer. Liquid Barcodes App API includes best effort checks to detect unusual/abusive operations and minimize impact in case an API key should still be exposed.
User models
These models are used by various requests related to user registration and user management.
String.
The User model
Contains all the user information about each user available to the app.
Parameter | Description |
---|---|
UserId | String. 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 | String. Users mobile number. |
Name | String. Optional: Name of user |
Address | String. Optional: Address of user |
PostCode | String. Optional: User's zip code |
City | String. Optional: User's city of residence |
String. Optional: User's preferred e-mail | |
DateOfBirth | Date. Optional: User's date of birth in ISO-8601 format (yyyy-mm-dd). |
Gender | String. Optional: User's gender specified as M or F. |
PreferredStores | Array. 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 | Array. 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 | Array. Optional: Array of userGroups for this user |
GroupId | String. A unique identifier for this group |
GroupDescription | String. A human readable description to be displayed to the user |
IsUserMember | Boolean. Only accepted values are 'True' or 'False', meaning that the user is part of the group or not part of the group, respectively |
UserConfigurable | String. 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' |
PaymentMethods | Array. Optional: Array of payment methods this user currently has registered. |
Id | Number (integer). Payment method ID. |
Title | String. Descriptive title that should be shown to the user, for example "MasterCard ending in 1234". |
Culture | String. Optional: Indicates the users culture / language. Must be one of the values from the /languages service. Values follow RFC 4646. |
Consents | Array. Array of consents (see Consent situation model) that is applicable 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 | String. Link to HTML page with advanced settings (including historic data for the user). If user has Msn PIN to register will be sent by Msn. Otherwise if user has Email - pin to register will be sent by Email. If both Msn and Email are empty - empty string is returned in UserMyPage parameter |
PlateNumber | String. Optional: Plate Number description. |
Id | Number (integer). Id of a plate number. |
PlateNumber | String. Plate number. |
Title | String. Title for a plate number. |
ExternalIdentifiers | Array. Optional: Array of external identifiers that are applicable to this user. If AppSettings.AvailableExternalIdentifiers are not configured - ExternalIdentifiers are populated only if user has value set. If AppSettings.AvailableExternalIdentifiers are configured - all available external identifiers are returned. Even if User has not populated identifier. |
Identifier | String. Optional: String that represents external identifier. |
Type | String. Type of the identifier. Supported types:
|
Name | String. A human readable localized name of Identifier to be displayed to the user (configured in AppSettings.AvailableExternalIdentifiers). |
Subscriptions | Array. Optional: Array of user’s subscriptions. If no subscription - empty array will be returned. |
PlanName | String. Name of the Subscription Plan, e.g. “Car wash Gold“. |
SubscriptionId | Integer. Id of the subscription. |
SubscriptionState | String. State of the Subscription, can be Active, Downgrading, Cancelled. |
The Consent model
The fields that make up a specific consent revision. It is used by the Consent situation mode below, which is in turn used by the appfeed services.
Field | Description |
---|---|
Id | The consent Id is an immutable ID for the version, any change in the consent text would mean a new ConsentId (even if the change is so minor that the ConsentVersion hasn't changed) |
Title | Localized / descriptive name. |
Version | This is a human readable consent version number of the latest valid consent |
Description | The exact consent text that the user is consenting too. |
PrivacyPolicy | Optional: The privacy policy text for the current consent version for the entire service |
DefaultState | Boolean flag. If true it means this consent can be checked as approved when presenting it to the user for the first time. |
RevokeWarningText | Optional: A text that must be shown to the user when trying to revoke this consent. |
MinimumAge | Optional: The minimum age of user to use this app. Given as a number of years |
MinimumAgeText | Optional: The text that is provided to indicate 'This app requires that you are X years or older'. This text must be shown to the user and she must either set a toggle to True or confirm by setting their birthdate. If the user did not confirm his age then this consent cannot be confirmed |
The Consent situation model
This model describes the current situation for all relevant consents, including what the user has approved and what he needs to approve.
Parameter | Description |
---|---|
Name | A value to indicate the consent type. The following values are defined for all applications: 'Master', 'Location', 'Push notification' |
State | The current state of this consent name for this user. It can take the following values:
'NoConsent' - No consent has every been given for this consent name 'ConsentGiven' - The user has given his consent for the ConsentId/Version details in LastApproved 'ConsentRevoked' - The user has given but since revoked his consent 'ConsentRenewalRequired' - The user has given his consent for the ConsentId/Version details in LastApproved, but a renewal of the consent is required to use this part of the service |
Mandatory | If true the user must consent to or renew this consent for the app to work, if the user hasn't already given his consent. If the user wants to revoke a mandatory consent, this will mean that the user opts out of the entire service. If false, this particular consent is not required for the service to work |
LastApproved | Consent object (see Consent model). The last revision the user has approved (may be revoked) of this consent name. If the user has never approved this will be null / not present. |
CurrentVersion | Consent object (see Consent model). The current / latest revision of this consent. |
ChangeLog | Optional: Array of change log from the last approved consent version to the current version |
Id The exact consent version as an Id | |
Version The consent version in a human readable form | |
Text A textual description of the changes that was introduced with this particular version from the previous ConsentId |
Register user with consent
If you do not already register customers on your side including correct consent handling, you must register user with consent in Liquid Barcodes system.
The high-level registration process is illustrated and described below (click image to enlarge):
The application identifies itself/the user in a two stage process, which is normally only carried out once. However the LIQUID services has the ability to force a re-registration either explicitly (hard) or implicitly (silent).
POST /initialize
The application identifies itself with a unique and persistent ID. As a response it is given a temporary UserId from the system that it is to use in all future function calls to this API and an array of consents.
- Consent handling. The API supports two types of consents: Master consents and Non-master consents. Master consent is identified through the consent situation model parameter Name= ‘Master’. User should accept Master consent on registration. As a minimum, user should be presented with the consent model title and link to Privacy policy text. Both texts are provided through the API.
- Age restrictions. App is responsible for verifying user’s age, either by collecting date of birth or presenting user with active consent mechanism (eg. toggle button or check box) and MinimumAgeText. User registration cannot be completed if DateOfBirth < MinimumAge.
- Texts can be provided as HTML converted from markdown.
POST /pin
After age verification and consent accept, the application calls this API again with a unique user identificator (normally phone number, but it may also be e-mail or in the response to this function call) together with the temporary UserID. The user is then sent a PIN on SMS (or e mail if that is preferred)
POST /user
The application calls this API with the unique temporary UserID, the received PIN code and consent accept (including age information). In addition additional information about the user may be added. Upon verification from the system that the UserID and PIN matches, the application gets a final UserID. The final UserID is either the same as the temporary UserID (user has never registered before) or a new UserID (in the case where the user has
previously registered). The function returns the processed user model (see User model).
PUT /User
If some mandatory user information is required for the application, and this was not provided with the POST /user call this should be updated to complete the registration process. This will typically involve granular consents:
- Non-master consents provide options for granular consents that can be handled after the main registration process or on ‘My page’. We advice to present users with all granular consents on one page. Present consent model title and link to consent model description.
It is important to note that several application instance can share the same UserID, if a particular user installs and register the application on several phones (as long as he has access to the phone that gets the PIN).
Store the UserID locally, not in clear text.
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 |
---|---|
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. |
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
|
---|---|
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 |
|
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).
If not present or null, current data will be unchanged. If empty string, current data will be removed. |
|
Name | Optional: Name of user.
If not present or null, current data will be unchanged. If empty string, current data will be removed. |
|
Address | Optional: Address of user.
If not present or null, current data will be unchanged. If empty string, current data will be removed. |
|
PostCode | Optional: User's zip code.
If not present or null, current data will be unchanged. If empty string, current data will be removed. |
|
City | Optional: User's city of residence.
If not present or null, current data will be unchanged. If empty string, current data will be removed. |
|
Emails | Optional: List of user's preferred e-mails.
If not present or null, current data will be unchanged. If empty string, current data will be removed. |
|
DateOfBirth | Optional: Users date of birth in ISO-8601 format (yyyy-mm-dd).
If not present or null, current data will be unchanged. If empty string, current data will be removed. Note: If there is a consent that requires a minimum user age, this field is mandatory. |
|
Gender | Optional: User's gender specified as M or F.
If not present or null, current data will be unchanged. If empty string, current data will be removed. |
|
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.
If not present or null, current data will be unchanged. If empty array, current data will be removed. |
|
Culture | Optional: Indicates the users culture / language. Must be one of the values from the /languages service. Values follow RFC 4646.
If not present or null, current data will be unchanged. If empty string, current data will be removed. |
|
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) | |
ExternalIdentifiers | Optional: Array of external identifiers that are applicable to this user.
If array is null no changes will be done to existing external identifiers. If array is not null - existing external references will be rewritten with the new list (identical to existing identifiers won't be changed (identifier+type)). |
|
Identifier String that represents external identifier. | ||
Type Type of the identifier. Supported types:
|
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).
If not present or null, current data will be unchanged. If empty string, current data will be removed. |
|
Name | Optional: Name of user.
If not present or null, current data will be unchanged. If empty string, current data will be removed. |
|
Address | Optional: Address of user.
If not present or null, current data will be unchanged. If empty string, current data will be removed. |
|
PostCode | Optional: User's zip code.
If not present or null, current data will be unchanged. If empty string, current data will be removed. |
|
City | Optional: User's city of residence.
If not present or null, current data will be unchanged. If empty string, current data will be removed. |
|
Emails | Optional: List of user's preferred e-mail.
If not present or null, current data will be unchanged. If empty string, current data will be removed. |
|
DateOfBirth | Optional: Users date of birth in ISO-8601 format (yyyy-mm-dd).
If not present or null, current data will be unchanged. If empty string, current data will be removed. |
|
Gender | Optional: User's gender specified as M or F.
If not present or null, current data will be unchanged. If empty string, current data will be removed. |
|
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).
If not present or null, current data will be unchanged. If empty array, current data will be removed. |
|
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.
If not present or null, current data will be unchanged. If empty string, current data will be removed. |
|
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) | |
ExternalIdentifiers | Optional: Array of external identifiers that are applicable to this user. If array is null no changes will be done to existing external identifiers. If array is not null - existing external references will be rewritten with the new list (identical to existing identifiers won't be changed (identifier+type)). |
|
Identifier | String that represents external identifier | |
Type | Type of the identifier. Supported types:
|
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.
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
|
---|---|
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.
Consent update
The API supports breaking and non-breaking changes. If a breaking change to either the Master consent or the Granular consents is introduced, users should accept the new consent texts.
The API may provide change description for each consent update back to previous accepted consent version. Note that there may be several new versions and corresponding change log texts for one user.
MASTER CONSENT
Breaking changes on Master consent will block the app from getting content until new consent has been accepted. Prompt user with updated consent version to restore app functionality. The app should check for, at regular intervals eg. daily, and warn user about non-breaking changes to Master consent. In case of non-breaking changes, the state in the Consent situation model will be set to 'ConsentRenewalRequired' for the Master consent. Use GET /user to retrieve updated consent texts.
GRANULAR CONSENTS
User can continue to use the app even if there is a breaking change to one or multiple granular consents. The app should check for, at regular intervals eg. daily, and warn user about any changes to Non-master consents. If change is identified, give user option to renew consent. In case of changes to the granular consents, the state in the Consent situation model will be set to 'ConsentRenewalRequired' for the applicable consent(s). Use GET /user to retrieve updated consent texts.
Register user - I create UserId & register consent myself
If you already register customers on your side with a unique and persistent ID for each individual user and correct consent handling, you can perform a simpler registration process that can be done silently to the end user.
USING THIS REGISTRATION METHOD IT IS THE CALLER’S RESPONSIBILITY TO HANDLE ALL CONSENTS AND MANAGEMENT OF THE USER’S DATA, AND FOR ENSURING USER IDENTITY UNIQUENESS AND PERSISTENCE. NOT ALL LIQUID BARCODES API FEATURES ARE AVAILABLE IN FOREIGN ID MODE.
It is important that the registration is done through the caller’s back end and not by the mobile application itself.
The main steps in this registration flow are:
- register user and consent in your system and create a unique and persistent UserID
- Register user in Liquid Barcodes system by posting your UserID using the POST /user request
- You are now ready to use your own UserId with App API functional requests. List of services that do not support third party UserIDs:
- Dashboard - User support: you must use LB internal IDs to look up users, eg. LB UserId or coupon codes
- Reports - data reports such as redemption reports use LB internal UserIDs
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).
Note: If there is a consent that requires a minimum user age, this field is mandatory. |
|
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
|
---|---|
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.
DELETE /user
Deletes a user profile. Expects the following parameters
Parameter
|
Description
|
---|---|
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
The service replies with HTTP-200 status when the operation was successful
GET /points-program/{UserId}/log/points
Obtain all historical transactions of earned, used and expired points:
Request
Parameter | Description |
---|---|
UserId | A unique ID for the user. Assigned by LIQUID. |
The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) +UserId + Your secret salt
Response
Parameter | Description | |
---|---|---|
LogData |
An array of log records | |
Type |
Points event type.
Possible values:
|
|
Timestamp |
Event date in UTC | |
PointsChange |
Amount of points change (also include bonus points if any) | |
BonusPoints |
Optional: Amount of bonus points received | |
NewBalance |
New giftcard balance after event | |
Description |
Description of an operation | |
ExpirationDate |
Optional: Date when issued points would be expired |
GET /points-program/{UserId}/history/points
Obtain historical data on points balance and transactions for a specific user in the indicated period:
Request
Parameter
|
Description
|
---|---|
UserId | A unique ID for the user. Assigned by LIQUID. |
PeriodType | Type of requested period. Valid values are ‘Days’ and ‘Months’. |
PeriodsNumber | An integer determining the length of the points history time series. For example 3 will return data for current period and previous 3 periods. |
The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) + UserId + Your secret salt
Response
Parameter | Description | |
---|---|---|
Data | An array of records for each period in the report | |
PeriodType | Type of requested period. Valid values are ‘Days’ and ‘Months’. | |
PointsBalance | Total points balance at the end of period | |
Timestamp | Start date of the period | |
Earned | Number of points earned in the period | |
Used | Number of points used in the period | |
Expired | Number of points expired in the period |
GET /points-program/{UserId}/history/store-activity
Return historical data organized in the way that it can be used to build visualizations and customer information:
Request
Parameter
|
Description
|
---|---|
Parameter
|
Description
|
UserId | A unique ID for the user. Assigned by LIQUID. |
PeriodType | Type of requested period. Valid values are ‘Days’ and ‘Months’. |
PeriodsNumber | An integer determining the length of the points history time series. For example 3 will return data for current period and previous 3 periods. |
The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) + UserId + Your secret salt
Response
Parameter | Description | |
---|---|---|
Data | An array of records for each period in the report | |
PeriodType | Type of requested period. Valid values are ‘Days’ and ‘Months’. | |
Timestamp | Start date of the period | |
MoneySpent | The amount of money spent in this period | |
Visits | The number of visits in stores in this period |
GET /points-program/{UserId}/tier-status
Will return required conditions to upgrade to the next tier and current status.
REQUEST
Parameter
|
Description
|
---|---|
Parameter
|
Description
|
UserId | A unique ID for the user. Assigned by LIQUID. |
The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) + UserId + Your secret salt
A successful call will return a HTTP 200 OK with the following format
RESPONSE
Parameter | Description | |
---|---|---|
CurrentTierName | Name of the user’s current tier. | |
NextTierName | Name of the next tier. | |
RollingDaysPeriod | Optional: The number of days in the current counted period. | |
Conditions | A list of conditions required for the next tier | |
ConditionType | The type of condition. Valid values are ‘Visits’, ‘Points’ or ‘MoneySpent’. | |
RequiredValue | The threshold value required to be promoted to next tier. | |
CurrentValue | User’s current value. RequiredValue minus CurrentValue is the additional number of ‘Visits’, ‘Points’ or ‘MoneySpent’ user must obtain to be promoted. | |
DegradationDate | Optional: This parameter will only be available for Tier logic v2 and if user's activity in the current period does not qualify for the current Tier. |
GET /points-program/{UserId}/history/issues
Will return a history of issued points including they expiration dates.
REQUEST
Parameter
|
Description
|
---|---|
Parameter
|
Description
|
UserId | A unique ID for the user. Assigned by LIQUID. |
The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) +UserId + Your secret salt
RESPONSE
Parameter | Description | |
---|---|---|
IssuedPoints |
An array of issue records | |
Timestamp |
Issue date in UTC | |
PointsChange |
Amount of points issued (also include bonus points if any) | |
BonusPoints |
Optional: Amount of bonus points received | |
RuleName |
Name of the triggered rule | |
ExpirationDate |
Date when issued points would be expired |
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 |
---|---|
ScheduleId integerRequired |
LIQUID Barcodes' internal Schedule identifier. |
ContentId integerOptional |
Required if content is issued.
LIQUID Barcodes content identifier. NOTE: The content identifier is only unique in scope of the content type (coupon, survey, game, ...). I.e. a game and a survey may, in theory, share the same ID. NOTE: For content that is shared by multiple users, for example web links, the ContentId may be 0 / zero. |
TopImageUrl stringOptional |
URL to the top image part of the content. Either TopImageUrl or ContentUrl has to be present. |
TopText stringOptional |
Not present if content is not issued.
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 |
BarcodeUrl stringOptional |
Not present if content is not issued.
Url to the barcode proper. This will have a small white border around it. |
BottomText stringOptional |
Not present if content is not issued.
Bottom text for the coupon. |
BottomImageUrl stringOptional |
Not present if content is not issued.
URL to a bottom image of a coupon. |
BackUrl stringOptional |
If present this points to an image to present on the back side of the content. |
BackMarkup stringOptional |
Content in markup language (for example HTML) that should be shown on the back side of the content. If present, should be used instead of BackUrl fields. |
ThumbUrl stringOptional |
If present this points to an smaller representation of the content to be used in an overview display |
ContentUrl stringOptional |
Not present if content is not issued.
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 |
BackgroundColour stringOptional |
If present this represents a background colour to use with this coupon. The background colour is represented in #AABBCC notation |
Type stringRequired |
Content type:
If the app feed returns an unknown or unrecognized app type the application should default back on the Coupon type |
Description stringOptional |
The content description. |
DescriptionMarkup stringOptional |
The content description in a markup language (for example HTML). If has value should be used instead of Description field |
SubText stringOptional |
Not present if content is not issued.
A short text to present with the content image. |
AmountLeft integerOptional |
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 |
ExpiryDate stringRequired |
ISO 8601 time/date after which the content will be expired. The expiration date/time is given in UTC |
IssueDate stringRequired |
ISO 8601 time/date when the content has been issued. The issue date/time is given in UTC |
RatingsCategory objectOptional |
The rating category to use. |
Id integerOptional |
The Id of the Rating category. |
Name stringOptional |
The name of the Rating category (e.g. COFFEE). |
ShareType stringOptional |
Can take the values ''NotSharable', 'Shareable' or 'ShareAndCare'. If not present then content is not shareable |
ValidForStore integerOptional |
Not present if content is not issued.
If the content can only be used in one particular store, this field has the StoreId value of this store |
ValidForStoreTags array of integerOptional |
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 |
GiftCardBalance numberOptional |
Not present if content is not issued.
Balance of the gift card |
Activated booleanRequired |
If true the coupon is already activated. If false the content must be activated before they can be used. If empty - no possibility to change the state of a coupon. |
IsPointsCard booleanRequired |
If true - it's a points program coupon, and we can get additional information for it (see GET /points-program/{UserId}/status/points-last-dats etc) |
Featured booleanRequired |
If true - this content should be promoted in the app (using pop-up or marked somehow) |
New booleanRequired |
If true - "New" mark should be added to content |
Like booleanOptional |
If true - content is liked. If false - content disliked. If null - no mark. |
LikeCounters objectRequired |
State of likes and dislikes for a content |
Likes integerRequired |
Count of likes. |
Dislikes integerRequired |
Count of dislikes. |
TagsData array of objectRequired |
An array of tags associated with this content, tags are grouped by types |
Type stringRequired |
Type of the Tags. |
Tags array of objectRequired |
An array of content tags (see Content Tag Model) of this type. |
RemainingValidations integerOptional |
Shows the number of remaining validations for the content. If NULL - there's no limit on number of validations |
AvailableStamps integerOptional |
Shows the number of the stamps on the current stage of a loyalty card. For regular coupons this field is NULL |
StampsRequired integerOptional |
Shows the number of the stamps required to fill loylaty card current level. For regular coupons this field is NULL |
AdditionalInfo1 stringOptional |
Additional content's info |
AdditionalInfo2 stringOptional |
Additional content's info |
AdditionalInfo3 stringOptional |
Additional content's info |
BarcodeNumber stringOptional |
Code prefix + coupon code |
IsSubscription booleanRequired |
Boolean flag to show if the object is associated with a subscription or not |
SubscriptionState stringOptional |
State of the subscription. Possible values:
|
SharedUser array of objectOptional |
Info about shared user |
Name stringOptional |
Name of a shared user. |
UserId stringOptional |
A unique ID for the given User that is assigned by LIQUID. |
ExternalUserId stringOptional |
A unique ID for the given User in external customer systems. |
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
|
---|---|
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 | Number. The Id of the section | |
Name | String. The name of the section | |
Content | Array of content objects (see Content model) that is placed in this section |
PUT /content/togglestate
Toggle the state of the content or activate promises.
The service expects the following parameters as part of the request body.
Parameter
|
Description
|
---|---|
UserId | UserId, a unique ID for the given User that is assigned by LIQUID. |
ContentId | Id of the content you want to change state. |
ScheduleId | ScheduleId of the content you want to change state. |
The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) + UserI + ContentId + Your secret salt
The service replies with HTTP-200 status when the operation was successful, the body of the response will contain:
Parameter
|
Description
|
---|---|
Parameter
|
Description
|
Content | Updated content model (see Content model) |
GET /preview
Gets an overview of public coupon previews. Can be used to show the list of available coupons before user is logged in.
Parameter
|
Description
|
---|---|
Parameter
|
Description
|
Culture | Optional: Desired culture of a coupons |
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 |
The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) + Your secret salt
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 |
GET /subscription-identifiers
Get a list of identifiers that can be used for a content object associated with a subscription. This endpoint should be called before calling POST /code/usage.
REQUEST
Parameter
|
Identifier
|
---|---|
Parameter
|
Identifier
|
UserId | UserId, a unique ID for the given User that is assigned by LIQUID. |
ContentId | The Id of the content. |
ScheduleId | LIQUID Barcodes' internal Schedule identifier. |
The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) + UserId + ContentId + Your secret salt
The service replies with HTTP-200 status when the operation was successful, the body of the response will contain the following model:
RESPONSE
Parameter | Description | |
---|---|---|
AddSubscriptionIdentifierMessage |
Optional: Message with information how to configure identifiers. If message is not empty - it should be shown after GET /subscription-identifiers request |
|
Identifiers |
An array of identifiers that can be used for this subscription. If it's empty - it means no identifiers are available, so AddSubscriptionIdentifierMessage will contain a message that the app should show to user | |
Identifier |
Identifier | |
Title |
User specified title for this identifier |
PUT /subscription/restart
Allows restart Subscription.
REQUEST
The service expects the following parameters as part of the request body:
Parameter | Description |
---|---|
UserId | String. UserId, a unique ID for the given User that is assigned by LIQUID. |
SubscriptionId | Integer. Id of the Subscription you want to restart. |
The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) + UserId + SubscriptionId + Your secret salt
RESPONSE
The service replies with HTTP-200 status when the operation was successful, the body of the response will contain the following model:
Parameter | Description |
---|---|
SubscriptionState | String. New Subscription state:
|
Likes
Allows users to like content. Information about likes can be used to filter / sort content in app and as input to machine learning.
PUT /content/{ContentId}/like
Allow set/remove like/dislike for content
The service expects the following parameters as part of the request body.
Parameter
|
Description
|
---|---|
Parameter
|
Description
|
UserId | UserId, a unique ID for the given User that is assigned by LIQUID. |
ContentId | Id of the content you want to like |
ScheduleId | ScheduleId of the content you want to like |
Like | Like state:
|
The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) + UserI + ContentId + Your secret salt
The service replies with HTTP-200 status when the operation was successful, the body of the response will contain:
Parameter | Description | |
---|---|---|
ContentId | Id of the content that was liked | |
ScheduleId | ScheduleId of the content that was liked | |
Like | New like state:
|
|
LikeCounters | Array of updated like\dislike counters for a content: | |
Like | Like state (true or false) | |
Count | Number of likes |
Tags
Makes it possible for users to prefer particular types of content. We support Category tags and Brand tags.
Content tag model
The content tag object is used in a several places and has next fields:
Parameter
|
Description
|
---|---|
Parameter
|
Description
|
TagId | The Id of the Tag |
Name | Name of the Tag |
ImageUrl | Optional: Image URL for a Tag image |
Likable | If true - user can set like or dislike for the content |
Dislikable | If true - no dislikes allowed (depends on the Likable flag, if Likable is false - no likes are allowed) |
Like | Optional: User Like state for this category (null - no value, true - liked, false - disliked) |
GET /content-tags
Returns the list of available Tags in the app. Can be used for filtering
The service expects the following parameters as part of the request body.
Parameter
|
Description
|
---|---|
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) + UserI + Your secret salt
The service replies with HTTP-200 status when the operation was successful, the body of the response will contain:
Parameter
|
Description
|
---|---|
Parameter
|
Description
|
Array of all Content Tags grouped by types | |
Type | Type of the Tags |
Tags | An array of content tags (see Content Tag Model) of this type |
PUT /content-tags/{TagId}/like
Allow set/remove like/dislike for Tag. Note: Method only works for Tags with flag Likable set to true
The service expects the following parameters as part of the request body.
Parameter
|
Description
|
---|---|
Parameter
|
Description
|
UserId | UserId, a unique ID for the given User that is assigned by LIQUID. |
TagId | Id of the target Tag |
Like | New like state:
|
The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) + UserI + TagId + Your secret salt
The service replies with HTTP-204 status when the operation was successful
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
|
---|---|
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
|
---|---|
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
|
---|---|
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
|
---|---|
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
|
---|---|
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
|
---|---|
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
|
---|---|
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:
|
|
TagIds | Optional: 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 | Optional: 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 | Optional: Store defined text to signify some special announcements, e.g. 'Closed on Monday due to public holidays' | |
Zip | Optional: Zip code. | |
City | Optional: City. |
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
Parameter
|
Description
|
---|---|
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
|
---|---|
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
|
---|---|
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.
Receipt Model
Receipt model that will be used
Parameter | Description |
---|---|
ReceiptId stringRequired |
Id of the receipt record (Will be used in POST /receipt/forward). |
Format stringRequired |
Receipt format, e.g. Liquid/1.0 for this field. The format is detailed below. |
Receipt stringOptional |
A JSON representation of the whole receipt for the complete transaction. The JSON should take format of the table bellow.
Note: The JSON code must be escaped so that the Receipt field is just a regular string. |
Receipt
Liquid/1.0 receipt format:
Parameter | Description |
---|---|
ReceiptId stringRequired |
A unique ID for this sale / receipt. |
SubTotal decimalOptional |
Summed amount of the saleslines. Includes rebates and tenders. Does not include tax. |
RebateOnSubTotal decimalOptional |
Total rebates. |
TenderOnSubTotal decimalOptional |
Total tenders. |
TaxSetupId integerOptional |
The tax setup used. |
TaxAmount decimalOptional |
Total amount of taxes. |
TaxDescription stringOptional |
Textual description of taxes for this item. Formatted for country conventions and member locale. |
TaxesInfo array of objectsOptional |
Array of taxes per tax category (combined for all items in the basket) |
TaxCategoryTitleCultureData stringOptional |
Title of the tax category (options for all supported cultures) |
TaxAmount decimalOptional |
Tax calculated for this item |
TaxPercentage decimalOptional |
Tax percent for the category |
TaxLegalEntityName stringOptional |
Hold information about tax legal entity |
StoreTaxIds dictionary<string, string>Optional |
Store specific tax identifiers for different tax categories |
TotalToPay decimalOptional |
Total amount to pay. Including tax. |
Currency stringOptional |
Currency unit for all monetary amounts. |
TransactionDateTime stringRequired |
Timestamp when the sale was completed (ISO-8601 format). |
GLN stringOptional |
Global Location Number (Wikipedia page). |
OrganizationNumber stringOptional |
Organization number of the store. |
Store objectRequired |
Information about the store |
StoreId integerOptional |
Unique Id of a store in Liquid Barcodes system. |
StoreRef stringOptional |
Store reference in POS system. |
ExternalStoreRef stringRequired |
The same and interchangeable with StoreRef. |
StoreName stringOptional |
Name of the store. |
POSId stringOptional |
Unique POS identifier. |
EmployeeId integerOptional |
Unique employee identifier. |
EmployeeName stringOptional |
Employee name. |
Customer objectRequired |
Information about store customer. |
id integerOptional |
Unique id of a customer in a LiquidBarcodes system |
loyalty_id stringOptional |
Coupon code that was used by the customer. Replaces userRef if filled. |
msn stringOptional |
Mobile number. |
userRef stringRequired |
User identifier (App user id or Foreign id). Can be replaced by loyalty_id. |
name stringOptional |
Full name. |
gender stringOptional |
Gender (M/F). |
birthdate stringOptional |
Birthdate (ISO-8601). |
Saleslines array of objectsOptional |
Sales lines in the receipt. |
Description stringOptional |
Description of the sales line. |
EAN stringOptional |
European Article Number / International Article Number (Wikipedia page). Replaces ProductCode if filled. |
ProductCode stringRequired |
The POS' internal identifier for the bought product. Can be replaced by EAN. |
PLU stringOptional |
Price Lookup Code (Wikipedia page) |
Quantity decimalRequired |
Bought quantity. Can be a decimal amount. |
Unit integerOptional |
Supported unit types:
|
Brand stringOptional |
Product brand. |
SalesPrice decimalRequired |
Total price per unit (exluding rebates and tenders, but including tax). |
TotalLinePrice decimalRequired |
Final price of the sales line. |
Rebate decimalRequired |
Rebate given per unit. |
Tender decimalRequired |
Tender given per unit. |
RebatedPrice decimalOptional |
Actual price per unit (including rebates, tenders and tax). |
Comment stringOptional |
Extra information about this line. |
TaxAmount decimalOptional |
Tax amount included in this sales line. |
TaxPercentage decimalOptional |
Tax percentage applicable for this sales line. |
TaxDescription stringOptional |
Textual description of taxes for this item. Formatted for country conventions and member locale |
LineTaxesInfo array of objectsOptional |
Array of taxes per tax category for this line. |
TaxCategoryTitleCultureData stringOptional |
Title of the tax category (options for all supported cultures) |
TaxAmount decimalOptional |
Tax calculated for this item |
TaxPercentage decimalOptional |
Tax percent for the category |
RewardPointsLines array of objectsOptional |
Information about points issued as a reward for this receipt |
Description stringOptional |
Points reward description. |
TotalPoints decimalOptional |
Given points amount. |
Payments array of objectsOptional |
Payment information |
type stringOptional |
Payment type, for example: Card, Cash |
card_issuer stringOptional |
For example: VISA; Mastercard, AmericanExpress |
card_issuer_country stringOptional |
For example: NO, SE |
terminal_id stringOptional |
Unique payment terminal identifier. |
terminal_print stringOptional |
|
transaction_id stringOptional |
Unique payment transaction ID. |
ref_auth stringOptional |
|
Ref stringOptional |
|
auth stringOptional |
|
bax stringOptional |
|
censored_card_number stringOptional |
Masked credit card number that can be safely shown on a receipt. |
amount decimalOptional |
Payment amount. |
tip_amount decimalOptional |
Additional tip amount. |
processing_fee decimalOptional |
Processing fee. |
currency stringOptional |
Currency of payment. |
ProviderData stringOptional |
Payment provider specific information. It can contain Payment reference or some special info, content depends on Payment provider used. |
Metadata stringOptional |
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" : "" , "Metadata" : "" , "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" : "" } } |
GET /receipts
The following parameters are expected in the URL query-string:
REQUEST
Parameter | Description |
---|---|
UserId stringRequired |
UserId, a unique ID for the given User that is assigned by LIQUID. |
StoreIds integerOptional |
Will limit the retrieved receipts to this list of stores. Should use the StoreId as available in the GET /stores call. |
DateFrom stringOptional |
ISO 8601 datetime string. It 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 as an SHA-2 256 checksum using string source from the following concatenated parameters:
- DateTime (HTTP header)
- UserId
- Your secret salt
Successful Response
The service replies with HTTP-200 status when the operation was successful with the following return values
Parameter | Description |
---|---|
Logo stringRequired |
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 |
Receipts array of objectRequired |
An array of Receipt Model objects. |
POST /receipts/forward
Use this service to forward receipts outside the app. The service expects the following parameters.
REQUEST
Parameter
|
Description
|
---|---|
Parameter
|
Description
|
MediaType | The media to forward the receipts, currently only 'Email' is accepted |
ReceiptIds | A list of receiptIDs to be forwarded (ReceiptId field from response of GET /receipts, NOT ReceiptID in Receipt field) |
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.
PUT /receipts/{ReceiptId}
This service allows you to update MetaData receipt field.
Parameter
|
Description
|
---|---|
Parameter
|
Description
|
UserId | UserId, a unique ID for the given User that is assigned by LIQUID. |
ReceiptId | Id of the receipt record (from GET /receipts) |
Metadata | Field for storing any additional information |
The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) + UserId + ReceiptId + Your secret salt
The service replies with HTTP-200 status with Receipt Model in the body of response (see Receipt Model) 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):
- 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.
- 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.
- When checkout of the basket is selected, the app sends a request to the shop back-end using the ProcessShopBasket call.
- 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
- 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.
- 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 integerRequired |
The unique ID for this particular offer. |
ContentId integerRequired |
LIQUID Barcodes content identifier. |
ScheduleId integerRequired |
LIQUID Barcodes schedule identifier. |
CategoryId integerRequired |
Id of offer's category. |
IssueDate stringRequired |
ISO 8601 formatted datetime when this offer instance was issued. Date/time is given in UTC. |
Like booleanOptional |
If true - offer is liked. If false - offer disliked. If null - no mark. |
PaymentProviderId stringRequired |
The ID of the payment provider where the OfferToken must be sent. |
MaximumAmount integerOptional |
The maximum number of times the offer can be bought. If not present or NULL it means unlimited. |
ThumbUrl stringOptional |
If present this points to an smaller representation of the shop offer to present on f.ex the front page of the application. |
Url stringRequired |
URL to the offer details image. |
BackgroundColour stringOptional |
If present this represents a background colour to use with this coupon. The background colour is represented in #AABBCC notation. |
Type stringRequired |
Defines the type of shop offer (Shop/Subscription/WebCouponShop/OrderAndPay/Local). |
Description stringOptional |
A textual description of the shop offer. |
ExpiryDate stringRequired |
ISO 8601 formatted datetime when this offer is no longer available . The expiration date/time is given in UTC. |
RetailPrice numberRequired |
The price to the consumer. |
DefaultPrice numberRequired |
The price without the discount. |
PersonalCalculatedPrice numberOptional |
The price offered to customer's that want to upgrade to a better plan. In the next renewal of the subcription, price will be full. |
TaxAmount numberRequired |
Tax percentage. |
TaxPercentage numberOptional |
Tax amount of the price to be paid in this particular payment. |
Currency numberRequired |
Will always be the currency of the app's country (one app, one country). |
OfferToken stringOptional |
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. NOTE: This property is marked optional because it will not be used in the case where Liquid Barcodes' own payment backend is used. |
OfferInstanceId stringRequired |
The unique instance ID for each individual shop offer |
ProductDescription stringOptional |
A textual description of the product. |
PurchaseConfirmationDescription stringOptional |
Contains message with instructions on what to do after successfull purchase (for example: Configure your subscription on MyPage). If this field is not empty - it should be shown after successfull POST /ProcessShopBasket request |
PurchaseConfirmationMessage stringOptional |
Contains message with information about purchase that user is going to do (for example: Subscription price: X$. Auto-renew: Y$). If this field is not empty - this message should be shown before purchase (before POST /ProcessShopBasket request) |
TagsData array of objectsRequired |
An array of tags associated with this content, tags are grouped by types. |
Type stringRequired |
Type of tags. |
Tags array of objectsRequired |
List of tags (see Content tag model) of the same type. |
DescriptionMarkup stringOptional |
The content description in a markup language (for example HTML). If has value should be used instead of Description field. |
AdditionalInfo1 stringOptional |
Additional offer's info. |
AdditionalInfo2 stringOptional |
Additional offer's info. |
AdditionalInfo3 stringOptional |
Additional offer's info. |
HasAvailablePromoCodes booleanRequired |
Shows whether this offer has active, live (active period between Start and Stop date) promo codes, that have not total usages limit or limit is not yet reached. Promo codes can be passed as OfferPromoCode in POST /ProcessShopBasket request for this shop offer. |
Featured booleanRequired |
If true - this content should be promoted in the app (using pop-up or marked somehow). |
New booleanRequired |
If true - 'New' mark should be added to content. |
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
|
---|---|
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. |
StoreId | Optional:Enables single shop offer pricing per store. If StoreId provided - prices for this store are returned. |
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 | Number. The Id of the category | ||||||||
Name | String. The name of category | ||||||||
ShopOffers | Array of content objects (see Shop offer model) that is placed in this category | ||||||||
OfferTokensExpiration | String. 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 /shopoffers/preview
Gets an overview of public shop offers previews. Can be used to show the list of available offers before user is logged in.
Request
The service expects the following parameters as part of the URL query-string:
Parameter
|
Description
|
---|---|
Culture | Optional: Desired culture of a shop offers and shop categories |
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) + Your secret salt
Response
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:
Parameter
|
Description | ||||||||
---|---|---|---|---|---|---|---|---|---|
Categories | Array of categories | ||||||||
Id | The Id of the category | ||||||||
Name | The name of category | ||||||||
ShopOffers | Array of shop offers objects (see Shop offer preview model below) that is placed in this category |
Shop offer preview model
This is how shop offer preview model looks like:
Parameter
|
Description | |
---|---|---|
ShopOfferId | The unique ID for this particular offer. | |
ScheduleId | The unique ID for the schedule. | |
CategoryId | ID of shop offer's category | |
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 (Shop/Subscription/WebCouponShop/OrderAndPay/Local) | |
Description | A textual description of the shop offer. | |
RetailPrice | The price to the consumer. 'Default price' for Subscription offers, 'Retail price' for single shop offers | |
Currency | Will always be the currency of the app's country (one app, one country). | |
ProductDescription
|
Optional: A textual description of the product. | |
LikeCounters | State of likes and dislikes for a content | |
TagsData | An array of tags associated with this content, tags are grouped by types | |
DescriptionMarkup | The content description in a markup language (for example HTML). If has value should be used instead of Description field | |
AdditionalInfo1 | Additional offer's info | |
AdditionalInfo2 | Additional offer's info | |
AdditionalInfo3 | Additional offer's info | |
Featured | If true - this content should be promoted in the app (using pop-up or marked somehow) | |
New | If true - "New" mark should be added to content |
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 stringRequired |
The UserId of the user |
StoreId integerOptional |
The Liquid Barcodes storeId is required if the offer can only be used at a given store. |
PaymentProviderId stringRequired |
The Liquid Barcodes Payment Provider Id. The appropriate value to use here will be provided by Liquid Barcodes. |
PaymentInformation objectOptional |
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. his parameter is a JSON object of Key:Value pairs. |
TotalBasketValue numberRequired |
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 array of objectsRequired |
An array of shop offers tokens that are to be processed. |
OfferInstanceId stringRequired |
The offer instanceId that is unique for this shop offer and UserId. |
Amount integerRequired |
The number of products to buy. This parameter have a value between 1 and MaximumAmount set in the shop offer. Currently only 1 is supported. |
OfferPromoCodeId integerOptional |
Promo code to apply to this shop offer. It has fixed price rebate. ID is received on verify promo code request. |
ReturnUrl stringOptional |
In case a user-present payment is configured, this URL should be set to tell the payment provider where to return after the user has done the payment.
We expect the URL will be a deep-link back into the app. A query parameter BasketId will be added to the URL, so that on return the job status on the relevant job can be checked (see the GET /ShopTransactionStatus service, set BasketId to the TransactionId). The return position must poll until a successful or failed transaction is seen. Please see the Polling policy section. |
The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) + UserId + PaymentProviderId + TotalBasketValue + Concatenated(OfferInstanceId + Amount + OfferPromoCodeId) + Your secret salt
A successful call will return a HTTP 200 OK with the following format:
RESPONSE
Parameter | Description |
---|---|
TransactionId stringRequired |
A reference to LIQUIDs internal transactionID. |
Timestamp stringRequired |
ISO 8601 formatted date and time when the reservation was completed. |
TotalValue numberRequired |
This is the total value that is used for the transaction. |
ShopOffers array of objectsOptional |
An array of shop offers tokens that are to be processed. The array is only present if the order has been fulfilled. |
OfferInstanceId stringRequired |
The offer instance Id that was purchased. |
Amount integerRequired |
The number of products bought. |
SuccessCode stringOptional |
On success returns:
|
SuccessMessage stringOptional |
A human readable response message when the call was successful. Only set when SuccessCode is set. |
RejectCode stringOptional |
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:
|
RejectMessage stringOptional |
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 basket ID. |
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 a value is set. See ProcessShopBasket response for details. | |
SuccessMessage | Success message | Optional. A human readable response message when the call was successful. Only set when SuccessCode is set. | |
RejectCode | Reject code | Optional. On rejection a value is set. See ProcessShopBasket response for details. | |
RejectMessage | Reject message | Optional. A human readable cause of rejection message in case a rejection occurred. Only set when RejectCode is set. |
POST /promo-codes/{PromoCode}/verify
Can be called to check promo code status for this promo code, shop offer and user. For valid promo codes It returns rebate configured for this promo code. During this request promo code is not used, reserved or applied in any way.
REQUEST
Parameter | Description | |
---|---|---|
UserId | The UserId of the user | |
PromoCode | A reference to LIQUIDs internal transactionID. | |
ShopOfferId | Optional: ID of the shop offer that owns the promo code. If empty - promo code can be applied to any shop offer |
The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) + UserId + PromoCode + ShopOfferId + Your secret salt
RESPONSE
Fieldname | Title | Description | |
---|---|---|---|
IsValidPromoCode | Is valid | Identifies if promo code can be used for this shop offer at this period by this user.
If promo code is not valid - Reject code will be set. |
|
PromoCodeId |
Promo code ID | Optional: ID of promo code found for this entered promo code string. ID should be passed with /ProcessShopBasket request. Only set when IsValidPromoCode is true. | |
SuccessMessage | Success message | Optional: A human readable response message when the promo code is valid. Only set when IsValidPromoCode is true. Can contain purchase confirmation message | |
RebateUnitType |
Rebate type | Optional: Rebate type of this promocode. Currently support only one value - FixedPrice. Only set when IsValidPromoCode is true. | |
RebateValue | Rebate value | Optional: Rebate value of this promocode. Only set when IsValidPromoCode is true. | |
RebatedPrice | Rabted price | Optional: Best price - take promo code price if better than existing offer price | |
RebatedPriceWithoutTax | Without Tax | Optional: Rebated price without Tax. Only set when IsValidPromoCode is true. | |
RejectCode | Reject code | Optional. A code that can be used to programatically recognize the cause of a promo code rejection. RejectCode will be present in the response if IsValidPromoCode is false.
The following values can occur:
|
|
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 following a flow like this:
- User has a coupon in app that was issued due to a subscription or a purchased shop offer and that coupon allows the user to get a product or service given by a machine (like car wash machine or coffee machine).
- When user is at machine place (that can be identified scanning a QR code), coupon is validated using the app that will send POST /code/usage request to Liquid Barcodes. User could take one of the available upselling options coming in GET /upselling-options response to use a different program that the one given by coupon with a configured surcharge.
- Once redemption is done, Liquid Barcodes back end will behave in one of the two following ways, depending on chosen configuration:
- Offline: code is validated, coupon marked as redeemed and response given to the app with no other interaction.
- Online: Liquid Barcodes is integrated with the machines and communicates that user wants to use that coupon, giving information about which programa is this code (or upselling option) for. Finally, code is validated, coupon marked as redeemed, response given to the app and machine activated to allow the user take the corresponding product or service.
Besides, this is also used to transfer stamps from paper loyalty card to app and many other functions.
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 stringRequired |
The UserId of the user |
TransRef stringRequired |
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 stringRequired |
The code to be reserved. |
StoreId integerOptional |
If the app is simulating a redemption from a store the StoreId must be present. |
Position objectOptional |
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 objectOptional |
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 numberRequired |
Longitude / meridian. Range from -180.0 (180 degrees west) to 180.0 degrees (180 degrees east). |
Latitude numberRequired |
Latitude / parallel. Range from -90.0 (south pole) to 90.0 degrees (north pole). |
Accuracy numberOptional |
The accuracy for the position in meters. |
Altitude numberOptional |
Altitude in meters, relative to sea level. |
AltitudeAccuracy numberOptional |
The accuracy for the altitude in meters. |
Speed numberOptional |
Current velocity of the device in meters per second. |
Heading numberOptional |
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 stringOptional |
Must be set when the attempt to acquire geographical location failed. Error classification. One of:
|
Error stringOptional |
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. |
Parameters stringOptional |
Customer specific parameters may be set here. We expect an object with string values. |
UpsellingOptionId integerOptional |
Selected upselling option. It's a value of the field Id in selected option from GET /upselling-options field Id. |
MachineProgramId integerOptional |
Selected machine program. It's a value of the field MachineProgramId in selected option from GET /upselling-options field MachineProgramId |
ReturnUrl stringOptional |
In case a user-present payment is configured, this URL should be set to tell the payment provider where to return after the user has done the payment.
We expect the URL will be a deep-link back into the app. A query parameter TransactionId will be added to the URL, so that on return the job status on the relevant job can be checked (see the GET /code/usage/paymentjob/{TransactionId}/status service). The return position must poll until a successful or failed transaction is seen. Please see the Polling policy section. |
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
Parameter | Description |
---|---|
LiquidLogRef integerRequired |
A reference to LIQUIDs internal logs. |
UniqueCode stringRequired |
The reserved unique coupon code. |
Timestamp stringOptional |
ISO 8601 formatted date and time when the reservation was completed. |
SuccessCode stringOptional |
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 stringOptional |
A human readable response message in case the codes was used. Only set when SuccessCode is set. |
SuccessModel stringOptional |
In some cases we need to return data to the app after a successful validation. The data model will be customer and situation dependant. This field will be returned as a string. Typically it will contain JSON. |
TriggerJobId stringOptional |
If this request could not be completed now but turned into a job, this is the job ID. The app must poll the job status from GET /code/usage/job/{TriggerJobId}/status until the result of the job is returned there. |
RejectCode stringOptional |
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 generic errors can occur:
The following giftcard specific errors can occur:
|
RejectMessage stringOptional |
A human readable cause of rejection message in case a rejection occurred. Only set when RejectCode is set. |
UserVisitUrl stringOptional |
In case user-present payment is set up, and a payment was required in the code usage operation, the URL that the user must visit is sent here. The user will be redirected to ReturnUrl after. |
PaymentTransactionId stringOptional |
In case user-present payment is set up, and a payment was required in the code usage operation, PaymentTransactionId is sent here. The app must poll the transaction status from GET /code/usage/paymentjob/{TransactionId}/status until the result of the transaction is returned there. |
GET /upselling-options
Get a list of upselling options available for the subscription coupon in particular store.
Parameter
|
Description
|
---|---|
UserId | UserId, a unique ID for the given User that is assigned by LIQUID. |
ContentId | The Id of the content. |
ScheduleId | LIQUID Barcodes' internal Schedule identifier. |
StoreId | The ID of the store where the coupon will be used. |
MachineId | Optional: Id of the machine to get only its available programs. |
The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) + UserId + ContentId + Your secret salt
The service replies with HTTP-200 status when the operation was successful, the body of the response will contain an array of:
Parameter
|
Description
|
---|---|
Id | Optional: Id of the upselling option (will be used in POST /code/usage field UpsellingOptionId). |
MachineProgramId | Optional: Id of the machine program (will be used in POST /code/usage field MachineProgramId). |
Name | Name of the option to display in the app. |
Price | Optional: Price you should pay to use this option. If null - it's a free option. |
PriceWithouTax | Optional: Price without tax you should pay to use this option. If null - it's a free option. |
UpsellingConfirmationMessage | Message to show on upselling confirmation. |
GET /code/usage/job/{TriggerJobId}/status
This service lets the app check the status of a job returned by a POST /code/usage request.
REQUEST
Parameter | Description |
---|---|
UserId | The UserId of the user |
TriggerJobId | The ID of the job to get the status for (value is sent in path). |
The signature is calculated by SHA-2 256 checksum of DateTime (HTTP header) + UserId + TriggerJobId + Your secret salt
A successful call will return a HTTP 200 OK with the following format:
RESPONSE
Parameter | Description | |
---|---|---|
TriggerJobId | The ID of the job. | |
JobStatus | The status of the job. Possible values: Pending, Done, Error. |
|
UseCodeResponse | The result of the job. | |
... | This field contains the same data as the POST /code/usage response. Please see that section. |
GET /code/usage/paymentjob/{TransactionId}/status
REQUEST
Parameter | Description |
---|---|
UserId | The UserId of the user. |
TransactionId | The ID transaction to get the status for (value is sent in path). |
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
Parameter | Description | |
---|---|---|
TransactionId | ||
JobStatus | The status of the job. Possible values: Pending, Done, Error. |
|
UseCodeResponse | The result of the job. | |
... | This field contains the same data as the POST /code/usage response. Please see that section. |
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. |
35 | 500 35 | POST/PIN | Invalid MSN country code. |
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]. |
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 |
67 | 500 67 | POST /pin | Unable to register deleted same day |
68 | 500 68 | POST /user | Too many devices has been used for the same MSN |
73 | 405 73 | GET /points-program/{UserId}/tier-status
GET /points-program/{UserId}/history/store-activity GET /points-program/{UserId}/history/points |
Points program is not properly configured for a customer |
77 | 500 77 | PUT /user | Plate number was updated last time less than 30 days |
80 | 500 80 | POST /content/coupons/{ContentId}/stamps/share | Friend user reference (MSN) in the request is empty |
81 | 500 81 | POST /content/coupons/{ContentId}/stamps/share | There is not enough stamps on the loylaty card to share |
82 | 500 82 | POST /content/coupons/{ContentId}/stamps/share | User with user reference from the field FriendUserRef in the request is not registered app user |
83 | 500 83 | POST /content/coupons/{ContentId}/stamps/share | Friend doesn't have required loyalty card to receive shared stamps |
84 | 500 84 | POST
/promo-codes/{PromoCode}/verify |
Invalid promo code |
85 | 500 85 | GET
/upselling-options |
Invalid store ID |
86 | 500 86 | POST
/points-program/points/share |
Invalid points amount - less or equal 0 |
87 | 500 87 | POST
/points-program/points/share |
Not enough points on balance to share |
88 | 500 88 | POST
/points-program/points/share |
Another points transaction problem |
89 | 500 89 | PUT/subscription/restart | Subscription Id value is invalid |
90 | 500 90 | PUT/subscription/restart | Subscription with this Id not found |
91 | 500 91 | PUT/subscription/restart | This subscription doesn't belong to this user |
92 | 500 92 | POST/ProcessShopBasket
POST/code/usage |
User is blocked
|
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¶metername1=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
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.
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 API key) is available on request.
The API Key is strictly confidential and must not be exposed. The customer is responsible to secure the API key. Liquid Barcodes management APIs relies on API keys being handled securely and do not include check for unusual/abusive operations.
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
SHA-2 256("2014-03-06T13:11:04Z5824abcd99liquid1234") = ae76588d46686f300efba39d674d178863607f654f22d00a6cb4e9ba05d73e4f
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.
|
||||||
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
|
---|---|
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:
|
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.
|
||||||
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
|
---|---|
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:
|
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
|
---|---|---|
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 stringRequired |
The name of the report. Currently the following reportnames are supported (required parameters in bracket):
|
Period stringOptional |
The period for the report. Currently the following options are supported: 'Day', 'Week', 'Month', 'Quarter'. |
Date stringOptional |
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. |
Date integerOptional |
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 stringOptional |
Link to the requested report. |
ResponseCode stringOptional |
A code that can be used to programatically recognize the state of response.
The following values can occur:
|
ResponseMessage stringOptional |
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 stringOptional |
A code that can be used to programatically recognize the cause of a rejection.
The following values can occur:
|
RejectMessage stringOptional |
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 )
- 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.
- The consumer selects which offer he wants by putting them into a basket.
- When checkout of the basket is selected, the app sends a request to the App provider's back-end for execution of the order.
- 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).
- If the step above fails, an appropriate payment-related error message should be provided to the consumer, and the process aborted.
- 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:
- Coupon has been issued successfully and should be counted towards the final payment.
- Coupon is not issued successfully and should not be counted towards the final payment.
- The App provider's back-end should commit the final transaction value to the payment provider.
- 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.
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:
- An encrypted PAYLOAD-KEY, encrypted with the payment providers public key.
- A JSON payload (specifed below) encrypted by key PAYLOAD-KEY.
Thus, the payment providers process to access the payload will be:
- Split the offertoken in two pieces, separated by pipe (|): KEY-X, PAYLOAD
- BASE64-decode KEY-X. Decrypt (RSA-1024) it with your private key. You now have PAYLOAD-KEY.
- Split PAYLOAD-KEY in two pieces, separated by pipe (|), you will get the IV (Initialization Vector) and key needed for payload decryption.
- BASE64-decode PAYLOAD. Decrypt (Rijndael) it with the IV and the key from PAYLOAD-KEY.
- 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:
|
||||||||||||||
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:
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
|
---|---|
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:
|
||||||||||
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:
|
||||||||||
RejectMessage | Optional. A human readable cause of rejection message in case a rejection occurred. Only set when RejectCode is set. |
List of errors:
HttpStatusCode.BadRequest, "InternalOfferToken expired";
HttpStatusCode.BadRequest, "Shop offer is inactive";
HttpStatusCode.Forbidden, "Duplicate call";
HttpStatusCode.Forbidden, "Maximum amount exceeded";
HttpStatusCode.Gone, "Campaign is out of codes";
HttpStatusCode.InternalServerError, "Error on coupon issue"; - other generic error on coupon issue
HttpStatusCode.InternalServerError, "InternalServerError"; - unknown generic error
Orders
Order model
This is the structure of the order object served in the GET /orders/list/{storeref} request:
Parameter | Description |
---|---|
OrderId stringRequired |
Order ID |
LocalPickUpTime stringRequired |
Pick up time (local timezone). Format - yyyy-MM-ddTHH:mm:ss |
Comment stringOptional |
Comment to order |
Products array of objectRequired |
Array of products in this order. |
Title stringRequired |
Title of the ordered product. |
Amount integerRequired |
Amount of the ordered product. |
Price numberRequired |
Price of the ordered product. |
Currency stringRequired |
Currency used to pay the ordered product. |
ProductCodes stringOptional |
Required Product Codes if configured in 'Order and Pay' campaign. Codes will be separated by comma (,). |
Customizations array of objectRequired |
Array that contains user customizations for the ordered product. |
Type stringRequired |
Customization type. It can be:
|
ProductCode stringRequired |
Code of customization product. |
Description stringRequired |
Description of customization product. |
Amount integerOptional |
If type is 'AddOn', it is set to indicate amount of added product. |
GET /orders/list/{storeref}
It will fetch sorted by pick up date filtered list of orders for this store.
Request Path parameters
Parameter | Description |
---|---|
StoreRef stringRequired |
The unique store ID. |
Request Query parameters
Parameter | Description |
---|---|
IsReceivedByPos integerOptional |
Value to filter orders received by POS. It can be:
No value means no filter. |
MaxPlaced stringOptional |
If set, only return orders placed before this point in time, non-inclusive. Format - yyyy-MM-ddTHH:mm:ss. |
MinPlaced stringOptional |
If set, only return orders placed after this point in time, inclusive. Format - yyyy-MM-ddTHH:mm:ss. |
MaxDelivery stringOptional |
If set, only return orders delivered before this point in time, non-inclusive. Format - yyyy-MM-ddTHH:mm:ss. |
MinDelivery stringOptional |
If set, only return orders delivered after this point in time, inclusive. Format - yyyy-MM-ddTHH:mm:ss. |
Note: If none of MaxPlaced, MinPlaced, MinDelivery or MaxDelivery filters is set, only orders with DeliveryDate in future will be returned.
The signature is calculated as an SHA-1 checksum using string source from the following concatenated parameters:
- X-Liquid-Date header
- StoreRef
- Your secret salt
Successful Response
A successful call to this function will return the following:
Parameter | Description |
---|---|
Orders array of objectRequired |
Array of order model objects. |
Error response
If the service fails it will reply with a non-HTTP-200 response or a response where RejectCode is set:
Parameter | Description |
---|---|
RejectCode stringOptional |
A code that can be used to programatically recognize the cause of a rejection.
The following values can occur:
|
RejectMessage stringOptional |
A human readable message for the cause of rejection. |
POST /orders/received/{storeref}
Set ReceivedByPOS date in the list of orders for this store
Parameter
|
Description
|
---|---|
Parameter
|
Description
|
StoreRef | The unique store ID |
OrderIds | Array of orders ids received by POS |
Checksum calculated from: X-Liquid-Date header + StoreRef + Your secret salt
A successful call to this function will return the following:
Parameter
|
Description
|
---|---|
Parameter
|
Description
|
OrdersProcessedCount | Number of orders processed |
If the service fails it will reply with a non-HTTP-200 response or a response where RejectCode is set:
Parameter | Description |
---|---|
Parameter | Description |
RejectCode | Optional. A code that can be used to programatically recognize the cause of a rejection.
The following values can occur:
|
RejectMessage | Optional. A human readable message for the cause of rejection. |
POST /orders/link/{storeref}
This service makes it possible to generate unique link to "View orders" page for a single store. To be used on combination with "Order and pay". The webpage gives store merchant overview of incoming orders without need for logging into local dashboard.
Service: POST https://api.barcodes.no/v3/orders/link/{storeref}
Parameter
|
Description
|
---|---|
Parameter
|
Description
|
StoreRef | The unique store ID |
Checksum calculated from: X-Liquid-Date header + StoreRef + Your secret salt
A successful call to this function will return the following:
Parameter
|
Description
|
---|---|
Parameter
|
Description
|
Link | Link to orders page |
JsonLink | Link to list of orders in JSON format |
Reject code: the service will reply with Reject code = NotFound for unknown stores.
Upload product codes
Will upload product codes list.
POST /product-codes/upload
Service: POST https://api.barcodes.no/v3/product-codes/upload
REQUEST
Parameter
|
Description
|
---|---|
Parameter
|
Description
|
ProductCodes | Array of products, see Product model below.
|
Product model specification
Parameter
|
Description
|
---|---|
Parameter
|
Description
|
ProductCode | Unique identifier for the product |
Description | Product description |
Level1Id | Optional. Unique Id of the level 1 of the product hierarchy to which the above product belongs |
Level1Name | Optional. Description of level 1 |
Level2Id | Optional. Unique Id of the level 2 of the product hierarchy to which the above product belongs |
Level2Name | Optional. Description of level 2 |
Level3Id | Optional. Unique Id of the level 3 of the product hierarchy to which the above product belongs |
Level3Name | Optional. Description of level 3 |
Checksum calculated from: X-Liquid-Date header + Your secret salt
RESPONSE
A successful call to this function will return the following:
Parameter
|
Description
|
---|---|
Parameter
|
Description
|
UploadedRowsCount |
Number of rows uploaded |
If the service fails it will reply with a non-HTTP-200 response or a response where RejectCode is set:
Parameter | Description |
---|---|
Parameter | Description |
RejectCode | Optional. A code that can be used to programatically recognize the cause of a rejection.
The following values can occur:
|
RejectMessage | Optional. A human readable message for the cause of rejection. |
GET /campaigns/list
GET https://api.barcodes.no/v3/campaigns/list
Will fetch all the active and planned campaigns
This api call doesn't need any input parameter. It will take the necessary parameter from the authentication headers
A successful call to this function will return a list of the following object
Campaigns list model specification:
Parameter
|
Description
|
---|---|
Parameter
|
Description
|
Country | Customer's country |
SectionId | Section ID |
CategoryId | Shop offer category |
CampaignName | Campaign Name |
CampaignId | CampaignId |
CampaignStartDate | Campaign Start Date |
CampaignStopDate | Campaign Stop Date |
ScheduleName | Schedule name |
ScheduleId | Schedule Id |
ScheduleStartDate | Schedule Start Date |
ScheduleStopDate | Schedule Stop Date |
CouponImageUrl | Coupon image url |
ThumbImageUrl | Thumb image url |
BackImageUrl | Back image url |
Description | Description cultured |
ContentType | Coupon, Survey, Game, ShopOffer |
MediaType | AppGeneric, Email, Sms, Paper, PushNotification, etc. |
Tags | Array of tags:
|
AdditionalInfo1 | Additional info 1 |
AdditionalInfo2 | Additional info 2 |
AdditionalInfo3 | Additional info 3 |
CodesData | Only applicable for 'Import codes' campaign. Contains data about imported codes set:
|
ParentScheduleId | Schedule ID of parent (only populated if parent is ShopOffer) |
FollowUpScheduleIds | Array of child schedule IDs (only populated for single purchase ShopOffers) |
FollowUps | Array of nested campaign models (only populated for single purchase ShopOffers) |
List of errors
All errors will contain these parameters in their body. Errors may be detected by the presence of RejectCode.
Parameter
|
Description
|
---|---|
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.9
- Added ShopTransactionReport report name to GetReport
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.
To use the APIs, Liquid Barcodes will share credentials including API key. The API Key is strictly confidential and must not be exposed. The customer is responsible to secure the API key. Liquid Barcodes management APIs relies on API keys being handled securely and do not include check for unusual/abusive operations.
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
|
---|---|
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):
For BASIC HTTP authentication:
|
||||||||||||||||||
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
|
---|---|
Parameter
|
Description
|
ListenerId | The ID of your listener. |
DELETE /listener
REQUEST
Parameter
|
Description
|
---|---|
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.
|
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:
|
POST /status-request
REQUEST
Parameter
|
Description
|
---|---|
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
|
---|---|
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:
Games:
Surveys:
|
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:
Games:
Surveys:
|
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
|
---|---|
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 |
---|---|
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.
- 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. - 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.
- 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.
<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.
To use the APIs, Liquid Barcodes will share credentials including API key. The API Key is strictly confidential and must not be exposed. The customer is responsible to secure the API key. Liquid Barcodes management APIs relies on API keys being handled securely and do not include check for unusual/abusive operations.
Standard POS Integration
Introduction
Watch this video or read the introduction to get a high level overview of the applicator service.
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.
Definitions:
- General rebate: a discount applied by POS that is available to all shoppers.
- Personal rebate: a discount applied by Liquid Barcodes that is available to registered members.
The main steps are:
- Customer identifies once in store. POS caches this ID.
- When all products have been added to the transaction, POS sends POST /applicator/sale request to Liquid Barcodes with:
- list of products (ProductLines). Link products to rebate lines if applicable. Disaggregate products that are linked to rebate lines.
- list of general rebates (RebateLines)
- customer identification (ShopperIdentifiers)
- Liquid Barcodes applies personal discounts and replies to the /applicator/sale request with adjusted transaction list.
- POS receives list of products and updated prices. POS makes new check to add general discounts.
- When customer has paid and transaction has been closed, POS sends finalizing request POST /applicator/sale/{SaleId}/finalization to Liquid Barcodes. If customer wants to add products or on unsuccessful payment, POS sends cancel request to Liquid Barcodes, also using POST /applicator/sale/{SaleId}/finalization and Cancel = TRUE.
The Standard POS integration uses the Applicator services – POST /applicator/sale and POST /applicator/sale/{SaleId}/finalization.
Applicator service – Sale
This service accepts the details of a sale from a POS, including products, general rebates and Liquid Barcodes identifiers, and applies all qualified Liquid Barcodes personal rebates to it.
The main flow is that the POS submits all details for its current sale, then uses the response to change or replace the sale.
The service can be called multiple times during sales process or just once when the sale is about to complete.
POST /applicator/sale
REQUEST
Fieldname | Description | ||
---|---|---|---|
Origin | Details of where this sale originated from. Mandatory for POST, not used for PUT. | ||
StoreRef | 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 | Optional. 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. | ||
InternalPosRef | 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”. | ||
OperatorRef | Optional. An anonymous identifier for the cashier using the cash register. If used this ID is at the discretion of the store. | ||
LegalEntity | 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. | ||
Sale | |||
Id | Unique sale ID. Must be unqiue for the customer. This may be a temporary ID if the POS does not obtain it’s transaction/sale ID before finalizing the sale. | ||
ProductLines | List of sales line objects. NOTE: Lines are processed in the order they are sent. | ||
Id | Unique ID for the line. Needs only be unique within this sale. A sequential numbering may be used, for example. | ||
ProductCode | Optional. Product code / identifier. These are the identifiers matches by campaign conditions. Required if the line is a sold item. For rebate lines added by the applicator service, the ProductCode will be LB-REBATE or LB-TENDER. |
||
ProductCodePrefix | Optional: Prefix that will be added in front of ProductCode when searching for products. | ||
Barcode | Optional. Scanned article number. | ||
Title | Optional. Text displayed in the POS. | ||
Price | Full price per unit on this line. Default 0. | ||
Tax | Tax amount per item on this line. Default 0. | ||
Quantity | Quantity of units sold. Default 0. Product lines Quantity should be split so that the full quantity of a line is either not discounted, or discounted by the same rebate (see RebatedBy). When we consider replacing rebates, the full Quantity of the is included by the rebate. |
||
Unit | Unit name, for example pieces, liters, kilograms. Default: Pieces. | ||
RebatedBy | Optional. Rebate reference. If this line is rebated point to the Id of the associated rebate line. |
||
OnlyQualifiesRebate | Optional: When set to true, it means this product line has qualified a rebate, but not been rebated itself. If a rebate has products that are only-qualifying and varying tax-rates, the TaxTotal calculation may be wrong unless this property is set. |
||
RebateLines | List of rebate line objects. NOTE: Lines are processed in the order they are sent. | ||
Id | Unique ID for the line. Needs only be unique within this sale. A sequential numbering may be used, for example. | ||
Title | Optional. Text displayed in the POS. | ||
Rebate | Optional. Rebate amount given (in total, not per unit). | ||
Tender | Optional. Tender amount given (in total, not per unit). The tender amount is a rebate that is still eligble for tax/VAT (because the seller is compensated). |
||
Irreplacable | When set to true, the rebate cannot be replaced during price minification. Default: false. | ||
ShopperIdentifiers | List of ShopperIdentifiers such as coupon ids, Userid. NOTE: Lines are processed in the order they are sent. | ||
Id | Unique ID for the line. Needs only be unique within this sale. A sequential numbering may be used, for example. | ||
Identifier | The code that identifies the shopper or the coupon, eg. a UserReference or scanned barcode. | ||
Type | Specifies what the Identifier field above contains and the processing mode: – Owner: initiates a one-scan for the owner given in Identifier. – Msn: initiates a one-scan for the owner whose mobile number is given in Identifier. – Code: initiates a one-scan for the owner of the code in Identifier. – SingleCode: initiaties a single reservation of the code given in Identifier. – ExternalIdentifier: resolves the external identifier and initiates a one-scan for the owner found. |
||
TaxTotal | The total taxes for this sale. | ||
Total | The total for this sale, taxes added and rebates deducted. | ||
TransientData | Free-to-use field which will be forwarded to the response.Can be used to send and keep additional data about the sale through this service, rather than persisting it on the POS side. This field is processed as a string and the content must be escaped as a valid JSON string. The content is otherwise decided by the client. |
||
Currency | The currency used on all monetary values in this sale. | ||
Nonce | A unique one-time value. All requests must use a unique nonce, however if the POS needs to re-send a request it must use the same nonce. If we have already processed that nonce, it will be rejected and duplicate processing is avoided. |
||
Decimals | Optional: If decimal rounding is desired, send the number of decimals to keep here. |
Signature
The signature source consists of the common header/salt data (see Calculation of the signature) and the following concatenated fields from this service:
- Nonce
- Origin.StoreRef
- Sale.Id
- Sale.TaxTotal (invariant culture)
- Sale.Total (invariant culture)
- For each Sale.ProductLines concatenate:
- Id
- ProductCode
- Barcode
- Title
- Price (invariant culture)
- Tax (invariant culture)
- Quantity (invariant culture)
- Unit
- RebatedBy
- For each Sale.RebateLines concatenate:
- Id
- Rebate (invariant culture)
- Tender (invariant culture)
- For each Sale.ShopperIdentifiers concatenate:
- Id
- Identifier
RESPONSE
Fieldname | Description | |||
---|---|---|---|---|
LiquidLogRef | A reference to LIQUIDs internal logs. | |||
Sale | Updated sale with campaigns applied. | |||
Id | Unique sale ID. | |||
ProductLines | List of sales line objects (same model as in request). | |||
RebateLines | List of rebate line objects (same model as in request). | |||
AccountingTags | Defined on the LB campaign and forwarded here. | |||
TaxTotal | The total tax for this sale. | |||
Total | The total for this sale, tax deducted. | |||
TransientData | Transient data forwarded from the request. | |||
Changes | List of changes done to the sale for this request. | |||
Action | One of: AddRebate, RemoveRebate… | |||
Id | Optional. The Id from the affected line. | |||
Warnings | List of warnings that the POS may want to show the user. | |||
Code | Possible warning codes: InvalidExternalIdentifier – a shopper identifier of type ExternalIdentifier was used, but we failed to find it. |
|||
Message | Optional.Readable message with further details. |
Applicator service – Sale finalization
Finalizing request
POST /applicator/sale/{SaleId}/finalization
REQUEST
Fieldname | Description | ||
---|---|---|---|
SaleId | ID of the sale to finalize. This may be a temporary ID if the POS does not obtain it’s transaction/sale ID before finalizing the sale. | ||
FinalSaleId | Optional. ID of the sale. If the POS does not obtain it’s transaction/sale ID before finalizing the sale, a temporary SaleId has been used up till now. The actual sale ID should then be set here. It will replace the temporary SaleId on our end. | ||
Cancel | When true, cancel the sale instead of completing it. |
RESPONSE
If the request is correct, the endpoint will return HTTP 204 with an empty body.
Request example:
POST /v3/applicator/sale HTTP/1.1 Host: validator.123.barcodes.no Content-Type: application/json X-Liquid-Timestamp: 2019-06-13T12:42:35+02:00 X-Liquid-Signature: 7835280A88C9E2626AC0F75B18DBCFC1BD57B736 Authorization: Basic ZGVtb3VzZXI6ZGVtb3Bhc3N3b3Jk cache-control: no-cache { "Origin": { "StoreRef": "ST0001", "PosRef": "POS0001", "InternalPosRef": "IPOS0001", "OperatorRef": "OP0001", "LegalEntity": "LE0001" }, "Sale": { "Id": "355f2bd4-4b06-41c3-b40d-e7a8bbc8ffe3", "ProductLines": [ { "Id": "f3faeb2a-c578-4e32-8299-eab37539a2e9", "ProductCode": "COFFEE", "Barcode": "111122223333", "Title": "Cup of black coffee", "Price": 20, "Tax": 5, "Quantity": 2, "Unit": "pieces", "RebatedBy": "" } ], "RebateLines": [ { "Id": "7e5a388d-7200-4c5b-b1b1-d81df0fe25e9", "Title": "Example Rebate", "Rebate": 0, "Tender": 0, "Irreplacable": false } ], "ShopperIdentifiers": [ { "Id": "1", "Identifier": "TDULC5BK133FEF1D74E1D9F2E4E84CAED1439", "Type": "Owner" } ], "TaxTotal": 10, "Total": 36.43, "TransientData": "" }, "Nonce": "b397912a-b6f9-4a36-8577-2fbf839e5ed9" }
Response example:
{ "LiquidLogRef": 1043405020, "Sale": { "Id": "355f2bd4-4b06-41c3-b40d-e7a8bbc8ffe3", "ProductLines": [ { "Id": "f3faeb2a-c578-4e32-8299-eab37539a2e9", "ProductCode": "COFFEE", "Barcode": "111122223333", "Title": "Cup of black coffee", "Price": 20, "Tax": 5, "Quantity": 2, "Unit": "pieces", "RebatedBy": "" } ], "RebateLines": [ { "Id": "7e5a388d-7200-4c5b-b1b1-d81df0fe25e9", "Title": "Example Rebate", "Rebate": 0, "Tender": 0, "Irreplacable": false }, { "Id": "b59621d3-e4cc-4606-8e51-74dc326ca646", "Rebate": 1.23, "Tender": 2.34, "Irreplacable": false } ], "TaxTotal": 10, "Total": 36.43, "TransientData": "" }, "Changes": [ { "Action": "AddRebate", "Id": "b59621d3-e4cc-4606-8e51-74dc326ca646" } ] }
Request example:
POST /v3/applicator/sale/355f2bd4-4b06-41c3-b40d-e7a8bbc8ffe3/finalization HTTP/1.1 Host: validator.123.barcodes.no Content-Type: application/json X-Liquid-Timestamp: 2019-06-13T13:19:59+02:00 X-Liquid-Signature: 4BF8116117404E1E858B8DD07E79A55BEE36ABED Authorization: Basic ZGVtb3VzZXI6ZGVtb3Bhc3N3b3Jk cache-control: no-cache { "SaleId": "355f2bd4-4b06-41c3-b40d-e7a8bbc8ffe3", "FinalSaleId": "bd0f6ee6-02ce-487c-b4b1-f8c4850a04ac", "Cancel": false }
Signature calculation example:
Timestamp: 2019-06-13T15:06:40+02:00 SaleId: 355f2bd4-4b06-41c3-b40d-e7a8bbc8ffe3 FinalSaleId: bd0f6ee6-02ce-487c-b4b1-f8c4850a04ac Cancel: 0 (1 means true, 0 means false) Salt: exampleSalt SignatureString = Timestamp + SaleId + FinalSaleId + Cancel + Salt = 2019-06-13T15:06:40+02:00355f2bd4-4b06-41c3-b40d-e7a8bbc8ffe3 bd0f6ee6-02ce-487c-b4b1-f8c4850a04ac0exampleSalt LowerCaseSignature = SHA1(SignatureString) = 371c1f119b4a169d4e1615f73da34414dd8900f5 Signature = UpperCase(lowerCaseSignature) = 371C1F119B4A169D4E1615F73DA34414DD8900F5
Cancel rebate request
This service allows the POS to delete one rebate line at a time. The service only deletes the rebate and the related coupon reservation(s), it does not trigger recalculation of personal rebates for the entire basket.
DELETE /applicator/rebate/{RebateId}
Signature
The signature source consists of the common header/salt data (see Calculation of the signature) and the following concatenated fields from this service:
RebateId
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:
|
||
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:
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:
|
|||
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:
|
|||
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:
|
|||
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: 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:
|
|
RejectMessage | Reject message | Optional. A human readable cause of rejection message in case an error occurred. Only set when RejectCode is set. |
Sales service
Introduction
This provides the POS with a mechanism to get additional coupons to print on the receipt. Based on sales rules configured in LIQUIDs platform the user may get additional coupon(s).
Since the validation service (see previous chapter) implicitly will trigger any sales-rule coupons too, this function should only be used when the validation service has not been called. If both the sale service and the validation services are used, the user would effectively get twice the amount of coupons he has qualified for.