Offer Sumission API
Introduction
The Offer Submission API is organized around REST. Our API has predictable resource-oriented URLs, accepts form-encoded request bodies, returns JSON-encoded responses, and uses standard HTTP response codes, authentication, and verbs.
This API gives users the ability to submit new offers for approval and assign offers to customers.
This API uses the oAuth2 client credentials grant type to secure all the communications. For more information, check the Authentication/Authorization guide.
Use Cases
A faster and error-proof way of creating offers
Offers Submission API gives to the CRM Ops Team a process to create offers with an UI simplified and smart, to increase the speed of offer synchronisation across the landscape while reducing failure rates, so that end users ability and trust increases to fully leverage the full capabilities of offers.
Benefits
Focus on improving the experience of creating offers for CRM Ops Team, the benefits of this new platform and API includes:
-
New digital experience for offers creators
The CRM Ops Team should have a new digital experience when creation offers, with a simple and intuitive user interface, and preview options, for a real time demonstration of how the offer would look both on the website or the app in the mobile devices.
-
Real time offer creation
A new capability of real time offer creation will be added to enable creating and updating offers in real time, across all systems involved in creating, managing and publish new offers. These offers can take seconds to create!
-
Reduce reengineering on offers creation process
During the creation of the new platform for offers creation, users were engaged in the process, having the opportunity to give feedback to improve the process, examine ways of working to achieve a streamline and simple process, and creating awareness in all functionalities in offers creation process.
It was also enabled the option to publish the offer to PROD from UAT, with appropriate approvals (reducing the need to recreate offers in PROD).
-
Real time error feedback
The new platform aims powering real time validation of the inserted values, previewing the offer during creation by simulating the different views and enabling end to end testing by assigning to test users in realtime, achieving minimum failure rates with near realtime error status report. The feedback provided to users enables editing failed offers rapidly, by letting them know what went wrong and how to fix the issues.
-
Reduce time-to-live of offers to the client
It was possible to create an ecosystem to synchronise the offers seamlessly across the landscape with minimum failure rate, since APIs creation could become the bedrock of automated processes, which increases the speed of creation of offers (eg. by reusing templates as base).
Time to create and publish offers was reduce from 10 days to 30 minutes, in some cases.
-
Increase clients trust on offers
Creating offers without errors and within minimum time to create and publish, and enabling end to end offers testing will result in tailored offers, more aligned with clients needs, increasing the level of trust that clients are having in the offers presented.
Marketing teams could react in-real-time to world changes, resulting in a well designed Offer Decision Engine and an improved match process between assigned offers to client according to each clients needs.
-
Multi Language Approach
Offer creators can now add details (eg. Offer title, description, messages, etc) in multiple languages based on the allowed languages of a market.
To help Reporting and Analytics teams, english details can be passed along also too, for non-English markets.
Quick Start Guide for Offer Submission API
This API is secured by OAuth 2.0. It uses the 'Client Credentials' Grant Type to allow the API consumer to access data. The process is details with the diagram below.
Base URLs
Auth API
| Environment | Base URL |
|---|---|
| QA | https://azmsauthqa.azurewebsites.net/ |
| UAT | https://azmsauthuat.azurewebsites.net/ |
| PROD | https://azmsauth.azurewebsites.net/ |
Offer Submission API
| Environment | Base URL |
|---|---|
| QA | https://offermanagementapis-qa.azurewebsites.net/ |
| UAT | https://offermanagementapis-uat.azurewebsites.net/ |
| PROD | https://offermanagementapis.azurewebsites.net/ |
1. Request a Client ID and a Client Secret
To use the Offer Submission API, you first need to request a Client ID and a Client Secret using Shell ServiceNow service.
Select the SIMAAS - Self-Service Application Onboarding (Production/Non-Production). First, you need to ask for non-Production access. When asked about an Application CI, select RTL_MOB_MICRO_OFFERS_MGMT PBS00719857.
2. Generate and provide Client ID and Client Secret
They will generate the credentials and send you by email.
3. Request an Access Token
Once you received the client credentials, just make a POST request to /auth/v1/token endpoint.
Request body parameters
| REQUEST BODY PARAMETER | VALUE |
|---|---|
| grant_type | Required It is the grant mode type, use client_credentials |
| client_id | It is the Client ID you received. |
| client_secret | It is the Client Secret you received. |
Sample Request
curl --location 'https://azmsauthqa.azurewebsites.net/auth/v1/token' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data '{
"grant_type": "client_credentials",
"client_id": "***",
"client_secret": "***"
}'
Response
On success, the response will have a 200 OK status and the following JSON data in the response body:
| KEY | VALUE TYPE | VALUE DESCRIPTION |
| --- | --- | --- |
| expires_at | string | The number of seconds since the epoch when this token will expire. |
| token | string | The access_token in JWT format. |
| token_type | string | The type of the token: Bearer. |
Note: This endpoint doesn't return a refresh token. Hence in case the bearer token expires the same endpoint should be called again to retrieve a new bearer token.
Sample Response
{
"expires_at": "1665767738",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
"token_type": "Bearer"
}
4. Initiate request to Offer Submission API with the Access Token from previous step
Every request you make to the Offer Submission API should include the Authorization header:
Header Parameters
| HEADER PARAMETER | DATA TYPE | DESCRIPTION |
|---|---|---|
| Authorization | String | This is a Bearer token. It should be the Access Token you got when you requested an Access Token before. Example: Bearer xxx where xxx is your Access Token.Example: Bearer xxx where xxx is your Access Token. |
Troubleshooting Authentication
The following table lists common authentication errors and potential causes:
| HTTP STATUS CODE | VALUE | POSSIBLE CAUSES |
|---|---|---|
| 400 | Bad request | Missing or incorrect parameters or header values. |
| 401 | Unauthorized | User not found. |
Fundamentals
Requests
The Offer Submission API provides a set of endpoints, each with its unique path. It is based on REST principles. Data resources are accessed via standard HTTPS requests in UTF-8 format. List of verbs in Offer Submission API:
- POST - Performs an action.
Responses
The responses always include a JSON object. Check the API documentation to find descriptions of common responses for each endpoint.
Response Status Codes
The Offer Submission API uses the following response status codes defined in RFC 2616 and RFC 6585.
- 200 - The request has succeeded. The Partner application can read the result of the request in the body and the headers of the response.
- 400 - Bad request. Due to malformed syntax, the server could not understand the request. The body will contain more information.
- 401 - Unauthorized. The request requires user authentication, and it has been refused for those credentials.
- 403 - Forbidden. The server understood the request but is refusing to fulfill it.
- 404 - Not Found - The requested resource could not be found. This error can be due to a temporary or permanent condition.
- 422 - Unprocessable content. The server understood the request but is unable to process it.
- 500 - Internal Server Error. This error should not happen but if you receive it, something went wrong, please report it to us.
Response Error Schemas
All error scenarios are returned with the same response body structure:
{
"error": {
"Developer": {
"appErrorCode": "string",
"message": "string",
"reason": "string"
},
"User": {
"appErrorCode": "string",
"message": "string",
"reason": "string"
}
},
"errorCode": 0,
"message": "string"
}
| KEY | VALUE TYPE | VALUE DESCRIPTION |
|---|---|---|
| errorCode | Int | The status code of the error. |
| message | String | The generic HTTP error message. For example, 500 is Internal Server Error. |
| error | JSON | An object with two JSONs with more details for the user and the developer. |
| error.User | JSON | An object with details for the User. |
| error.User.appErrorCode | String | An error code from the Offer Submission API. |
| error.User.message | String | An error message you can show to your users. |
| error.User.reason | String | A reason message. |
| error.Developer | JSON | An object with details for the User. |
| error.Developer.appErrorCode | String | The same error code from the Offer Submission API. |
| error.Developer.message | String | An error message giving details about the error. This can be useful for debugging your application. |
| error.Developer.reason | String | A reason message. |
Versioning
Your API version controls the API behavior you see (what properties you see in responses, what parameters you're allowed to send in requests, and so on). Your version is set in the URL. When a breaking change is introduced to the Offer Submission API, an updated version is released. The current version is v1. This is the only version available at this moment.
Backwards-compatible changes
We consider the following changes to be backward-compatible:
- Adding new API resources.
- Adding new optional request parameters to existing API endpoints.
- Adding new properties to existing API responses.
- Changing the order of properties in existing API responses.
- Changing the length or format of opaque strings, such as object IDs, error messages, and other human-readable strings.
Security
The Offer Submission API forces HTTPS for all services using TLS (SSL).
The Offer Submission API uses IP Whitelisting to help prevent attacks against the API. Only trusted IP addresses will be able to submit requests to the API.
List endpoints and resource name
- Request an Access Token
- Retrieve information about the version and environment
- Create and submit an offer
- Assign an offer to a customer
Request an Access Token
This endpoint of the Auth API https://azmsauthqa.azurewebsites.net/auth/v1/token uses the HTTP POST method.
Request body parameters
| REQUEST BODY PARAMETER | DATA TYPE | LIMITS (MIN/MAX) | NULLABLE | VALUE |
|---|---|---|---|---|
| grant_type | String | Enum values: client_credentials, authorization_code, refresh_token |
No | Required It is the grant mode type, use client_credentialsExample: client_credentials |
| client_id | String | N/A | No | It is the Client ID you received. Example: ti6lsuPEhcmBVxm5 |
| client_secret | String | N/A | No | It is the Client Secret you received. Example: dJiWaKdVuVojMBAfaYUPDi84zvVLlWivFy7s1qLFiToNejESGn12rAybrtNoolj |
Sample Request
curl --location 'https://azmsauthqa.azurewebsites.net/auth/v1/token' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data '{
"grant_type": "client_credentials",
"client_id": "***",
"client_secret": "***"
}'
When you request an Access Token, the Auth microservice will contact the Identity Provider System to get an Access Token using the client credentials provided. After getting one, the Auth microservice will ensure the user exists on our database and generate a new JWT token with the user roles, the email, and the UUID of the user. This will be returned to you alongside the token type and the expiration date of the Access Token.
Response
On success the response will have a 200 OK status and the body of the response will contain a simple JSON object with:
| KEY | NULLABLE | VALUE TYPE | DESCRIPTION |
|---|---|---|---|
| expires_at | No | String | The number of seconds since epoch when this token will expire. |
| token | No | String | The access token in JWT format. |
| token_type | No | String | The type of the token: Bearer. |
Sample Response
{
"expires_at": "1665767738",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
"token_type": "Bearer"
}
Exception Handling
The format of errors is always the same and specified in the Fundamentals section. For this endpoint, this is the list of errors:
| HTTP CODE | Description | Scenarios/Use case |
|---|---|---|
| 400 | Bad Request | Some of the parameters are not valid. |
| 401 | Unauthorized | The user does not exist. |
Retrieve information about the version and environment
This endpoint of the Offer Submission API https://offermanagementapis-qa.azurewebsites.net/api/v1/about uses the HTTP GET method.
Headers parameters
| HEADER PARAMETER | DATA TYPE | LIMITS (MIN/MAX) | NULLABLE | DESCRIPTION |
|---|---|---|---|---|
| Authorization | String | N/A | No | This is a Bearer token. It should be the JWT token you got when you requested an Access Token before. Example: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c |
| countryCode | String | 2 characters | No | Country code in two characters ISO 3166-1 alpha-2 format. The possible values are GB, PL, BG, PH, HU.Example: GB |
Sample Request
curl --location 'https://offermanagementapis-qa.azurewebsites.net/api/v1/about' \
--header 'Authorization: Bearer ***' \
--header 'countryCode: GB' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json'
Response
On success the response will have a 200 OK status and the body of the response will contain a simple JSON object with the following fields:
| KEY | NULLABLE | VALUE TYPE | DESCRIPTION |
|---|---|---|---|
| environment | No | String | It can be one of the following values: qa, uat, and prod. It is the environment of the Offer submission API you are currently using. |
| version | No | String | It is the version of the Offer Submission API you are currently using. |
Sample Response
{
"version": "1.3.0-03bc15a6f29f8b4bfb55148c6d877e37ec5fe4f5",
"environment": "qa"
}
Exception Handling
The format of errors is always the same and specified in the Fundamentals section. For this endpoint, this is the list of errors:
| HTTP CODE | Description | Scenarios/Use case |
|---|---|---|
| 401 | Unauthorized | The user token is not valid anymore or missing. |
| 403 | Forbidden | The user does not have permissions to do this action. |
| 422 | Unprocessable Content | Mandatory fields are missing (countryCode for example). |
Create and submit an offer
This endpoint of the Offer Submission API https://offermanagementapis-qa.azurewebsites.net/api/v1/offers/submit uses the HTTP POST method.
Headers parameters
| HEADER PARAMETER | DATA TYPE | LIMITS (MIN/MAX) | NULLABLE | DESCRIPTION |
|---|---|---|---|---|
| Authorization | String | N/A | No | This is a Bearer token. It should be the JWT token you got when you requested an Access Token before. Example: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c |
| countryCode | String | 2 characters | No | Country code of the offer in the two characters ISO 3166-1 alpha-2 format. The possible values are GB, PL, BG, PH, HU.Example: GB |
Request body parameters
| REQUEST BODY PARAMETER | DATA TYPE | LIMITS (MIN/MAX) | NULLABLE | DESCRIPTION |
|---|---|---|---|---|
| acceptanceRequired | Boolean | true / false |
Yes | Specifies if the customer must accept the offer assigned. Example: true |
| accumulative | Boolean | true / false |
Yes | If it is true, the offer can be assigned to the customer more than once at the same time. The maximum of the owned offers is the numberOfUsage.Example: false |
| assignableFrom | Date | Lower than assignableTo. Cannot be a past date. |
No | Date from when the offer is available to be assigned to customers. Use the ISO 8601 date format YYYY-MM-DD.Example: 2023-12-01. |
| assignableTo | Date | Greater than assignableFrom. Cannot be a past date. |
No | Date until offer is available in the markets offer bank to be assigned from the offer bank. Use the ISO 8601 date format YYYY-MM-DD.Example: 2023-12-02. |
| costOfReward | Number (double) | Only float values with a maximum of 2 decimals. Minimum is 0.00. |
Yes | Specify how much it costs the market to give this reward. Example: 12.25 |
| customText | Array of objects | N/A | No | A summary of the offer for each language. |
| customText.language | String | 2 characters | No | The language used for the summary. Example: en |
| customText.text | String | Max length is 4000 characters. | No | The text for the summary of the offer. Example: Fill min 1L of any fuel and get 200 pts. |
| deactivationAllowed | Boolean | true / false |
No | If it is set to true, the redemption of the offer can be activated/deactivated by the customer. A deactivated offer is not redeemable.Example: true |
| displayOrder | Number (integer) | Min is 1. Max is 99. |
No | Priority of offer display in the offer inbox. A lower number means higher priority. 0 will be on top.Example: 20 |
| expirationDays | Number (integer) | Min is 1. Max is 999999999999 |
Yes | Defines the number of days the customer has to redeem the reward (is only applied if this extends the offer's validity for that customer). Example: 30 |
| expirationDaysAchievement | Number (integer) | Min is 1. Max is 999999999999 |
Yes | Defines the number of days within which the customer has to achieve the offer (is only applied if this extends the offer's validity for that customer) Example: 30 |
| gameDetails | Object (JSON) | N/A | No, only when offerType is:- TARGETED_GAME_MASS- GAME_MASSYes, for other offerType. |
Contains fields related with TARGETED_GAME_MASS and GAME_MASS offer types. |
| gameDetails.campaignOverviewImage | String | Max length is 200 characters. | No | ID of the campaign image displayed on the app. Example: 82dc5ab1-1ceb-5cfe-b100-8cdfa4b306a6 |
| gameDetails.gameDescription | Array of objects | N/A | No | The brief description of the game to be displayed to the customer via the App for each language. |
| gameDetails.gameDescription.language | String | 2 characters | No | The language used for the brief description. Example: en |
| gameDetails.gameDescription.text | String | Max length is 100 characters. | No | The text for the brief description of the game. Example: Play every day and get 200 points. |
| gameDetails.gameIcon | String | Max length is 200 characters | No | Dynamo/COCO ID. This ID is for identifying the icon image on mobile view. Example: 1234567890 |
| gameDetails.gameTANDCURL | String | Max length is 200 characters | No | The URL of the page(s) of Terms and Conditions of the game play for the game described. Example: http://www.example.com/terms |
| gameDetails.gameType | String | Enum values: Luck Game , Skill Game or Knowledge Game. |
No | The description of the type of game that is defined by the Game description and URL. Example: Luck Game |
| gameDetails.gameURL | String | Max length is 120 characters | No | The full URL of the game. Example: http://www.example.com |
| gameDetails.inviteDurationDays | Number (integer) | Min is 0. Max is 999999999999 |
No | The number of days before the invite expires. Must be rounded up to the last day’s midnight when expiring invites. Example: 100 |
| gameDetails.prizeDescription | Array of objects | N/A | No | An array with the descriptions of the possible prizes that may be won if the motorist wins the game for each language. |
| gameDetails.prizeDescription.language | String | 2 characters | No | The language used for the description of the possible prizes. Example: en |
| gameDetails.prizeDescription.text | String | Max length is 4000 characters. | No | A description of the possible prizes. Example: This a prize description. |
| initiallyActive | Boolean | true / false |
Yes | Specifies if offer is immediately active after assignment. Example: true |
| isDefault | Boolean | true / false |
No, only when offerType is:- STAMP_SURPRISE- GFR_SURPRISEYes, for other offerType. |
If there is no personalized surprise offer assigned to the customer when the counter is fulfilled the customer will get the offer marked with this field true. Only one of these offers can exist per market per offer type.Example: false |
| numberOfAssign | Number (integer) | Min is 0. Max is 999999999999 |
No, only when offerType is:- TARGETED_BASIC_MASS- TARGETED_SEASONAL_BASIC_MASS- CONDITIONAL- SURPRISE- GOODWILL- PARTNER_BMO- PARTNER_SURPRISE- WELCOME- POINT_CONDITIONALYes, for other offerType. |
Specifies how many times the offer can be assigned to a single customer (0 = unlimited) Example: 3 |
| numberOfUsage | Number (integer) | Min is 0. Max is 999999999999 |
No, only when offerType is:- CONDITIONAL- SURPRISE- GOODWILL- PARTNER_SURPRISE- WELCOME- POINT_CONDITIONAL- TARGETED_GAME_MASS- GAME_MASSYes, for other offerType. |
Specifies how many times the offer can be used by single customer per assignment. Example: 0 |
| offerAchievementRule | Array of objects | N/A | No, only when offerType is:- CONDITIONAL- TARGETED_GFR_COUNTER- GFR_COUNTER- STAMP_COUNTERYes, for other offerType. |
Defines rules the user must accomplish to earn a reward. The relationship between the rules is OR. If the achievementRuleType is COMBINED_PRODUCT_PURCHASE then the relationship will be AND. |
| offerAchievementRule.achievementRuleType | String | If offerType = CONDITIONAL,then Enum values: - PRODUCT_PURCHASE- PRODUCT_PURCHASE_VALUE- COMBINED_PRODUCT_PURCHASE.If offerType = TARGETED_GFR_COUNTER\|GFR_COUNTER\|STAMP_COUNTER,then Enum values: - PRODUCT_PURCHASE- PRODUCT_PURCHASE_VALUE |
No | Defines what the customer needs to do in order to earn a reward. - PRODUCT_PURCHASE means the offer can be achieved by purchasing the number of certain producs, detailed by requiredQuantity.- PRODUCT_PURCHASE_VALUE means the offer can be achieved by purchasing a specific value of certain products, detailed by requiredQuantity.- COMBINED_PRODUCT_PURCHASE means the offer can be achieved by purchasing both the number of products, detailed by requiredQuantity, and the products defined within another offerAchievementRule having the achievementRuleType COMBINED_PRODUCT_PURCHASE within the same offer.Example: PRODUCT_PURCHASE |
| offerAchievementRule.excludeProducts | Array of Strings | Each string must have between 0 and 12 characters. | Yes | Defines the list of products that must not be included in the transaction to achieve the offer. Example: CG0000000163 |
| offerAchievementRule.includeProducts | Array of Strings | Each string must have between 0 and 12 characters. | Yes | Defines the list of products that must be included in the transaction to achieve the offer. Example: CG0000000123 |
| offerAchievementRule.label | String | Min is 0. Max is 100. |
No, only when offerType is CONDITIONAL.Yes, for other offerType. |
Label given to the achievement rule (used if more than one rule). Example: Rule 1 |
| offerAchievementRule.progressIncrement | Number (integer) | Min is 1. Max is 999999999999. |
No, only when offerType is:- TARGETED_GFR_COUNTER- GFR_COUNTER- STAMP_COUNTERYes, for other offerType. |
Number of stamps awarded to the customer for fulfilling the achievement rule. Example: 100 |
| offerAchievementRule.requiredQuantity | Number (integer) | Min is 0. Max is 999999999999. |
No | The required quantity, units/litres/monetary value, to be purchased in each transaction. Example 50 |
| offerAchievementRule.requiredTransactions | Number (integer) | Min is 0. Max is 999999999999. |
No, only when offerType is CONDITIONAL.Yes, for other offerType. |
Defines how many transactions need to be made so that offer gets achieved. Example: 10 |
| offerBackground | String | Max length is 200 characters. | No | Dynamo/COCO ID. This ID is for displaying background image on web/mobile view. Example: 82dc5ab1-1ceb-5cfe-b100-8cdfa4b306a6 |
| offerCode | String | Max length is 30 characters. |
Yes, only when offerType is:- BASIC_MASS- SURPRISE- CONDITIONAL- POINT_CONDITIONAL- TARGETED_BASIC_MASSS- PARTNER_BMONo, for other offerType. |
Unique code for each offer, used to refer to offers in tech offer list and data brief. Example: 1234567890 |
| offerDescription | Array | N/A | No | Description of the offer for each language. |
| offerDescription.language | String | 2 characters | No | Language of the description of the offer. Example: en |
| offerDescripcion.text | String | Max length is 4000 characters. | No | Description of the offer. Example: Fill min 1L of any fuel and get 200 pts |
| offerName | String | Max length is 100 characters. | No | Name of the offer. Example: New offer |
| offerReceiptMessage | Array of objects | N/A | Yes | Custom receipt message triggered when the offer is rewarded for each language. |
| offerReceiptMessage.language | String | 2 characters | No, if the array is not nil. | Language of the receipt message. Example: en |
| offerReceiptMessage.text | String | Max length is 4000 characters | No, if the array is not nil. | Custom receipt message triggered when the offer is rewarded. Example: Fill min 1L of any fuel and get 200 pts |
| offerResetDay | Number (integer) | Min is 1. Max is 28. | No, only when offerType is PARTNER_BMO.Yes, for other offer_type. |
Day of month when the offer reward limit is reset. Example: 12 |
| offerRewardConditionRule | Array of objects | - If offerType = POINT_CONDITIONAL, then exactly 2 objects are required.- If offerType = TARGETED_GAME_MASS\|GAME_MASS\|TARGETED_BASIC_MASS\|TARGETED_SEASONAL_BASIC_MASS, then exactly 1 object is required.- If offerType = STAMP_SURPRISE\|GFR_SURPRISE, then the min number of objects is 0 and max is 2.- For other offerType, only one condition rule is allowed. |
Yes, only when offerType is:- WELCOME- GOODWILL- PARTNER_SURPRISE- PARTNER_BMONo, for other offer_type. |
Defines the condition the customer’s transation must meet to get the offer rewarded. |
| offerRewardConditionRule.conditionRuleType | String | Enum values: - SPENT_AMOUNT- PRODUCT_PURCHASE- PRODUCT_PURCHASE_VALUEIf offerType = POINT_CONDITIONAL, then also:- REQUIRED_POINT_VALUE |
No, if the array is not nil. | If offerType = POINT_CONDITIONAL, then one of the offerRewardConditionRule object is of type REQUIRED_POINT_VALUE and the other is of another type.Example: SPENT_AMOUNT |
| offerRewardConditionRule.productCode | String | Max is 12 characters. |
No, if the array is not nil. More details in description. | If offerType = POINT_CONDITIONAL, then this field is required for the first rule. For the second rule, is optional.It is a Product Custom Group code. This code must exist in LoD. Example: CG0000000163 |
| offerRewardConditionRule.requiredValue | Number (double) | Max is 9999999999.0. |
No, if the array is not nil. | The value for which the OFFER_REWARD_CONDITION_RULE_TYPE must be met for the offer to be rewarded. - SPENT_AMOUNT: the value of the basket (before any discounts applied).- PRODUCT_PURCHASE: how much of a given product the customer must buy.- PRODUCT_PURCHASE_VALUE: the value of a given product purchased (without the offer applied).- REQUIRED_POINT_VALUE: the customer must have at least these many points on her account.Example: 12.5 |
| offerRewardRule | Object (JSON) | Only one reward rule by offer. | Yes, if offerType is:- STAMP_COUNTER- TARGETED_GFR_COUNTERNo, for other offerType. |
One offer can contain one reward rule. |
| offerRewardRule.productCode | String | Max is 12 characters. |
No | The product custom group for which the offerRewardRule is applicable. It must exist in LoD.Example: CG0000000163 |
| offerRewardRule.rewardIncrement | Number (integer) | Max is 9999999999. |
Yes | Unit of measure for getting reward. Calculation of reward quantity:[ROUNDING(Quantity / rewardIncrement)] * rewardIncrementThe rounding rule is defined by rounding.This field is only usable in case of ruleType is:- UNIT_BASED_PERCENTAGE- UNIT_BASED_DISCOUNTExample: 1000 |
| offerRewardRule.rewardLimit | Number (double) | Max is 9999999999.0 |
No, if offerType = PARTNER_BMO and ruleType = UNIT_BASED_PERCENTAGE\|UNIT_BASED_DISCOUNT.Yes, for other offerType. |
Quantity based limit for unit-based reward rule types. This field is only usable in case of ruleType is:- UNIT_BASED_PERCENTAGE- UNIT_BASED_DISCOUNTExample: 1000.5 |
| offerRewardRule.rewardValue | Number (double) | Max is 9999999999.0 |
No | It is the value of the reward, depends on the ruleType:- FIX_POINTS: Number of points to be rewarded to the customer.- POINTS_MULTIPLIER: In this case, the customer gets the basic points (from basic awarding rules), and in a separate detail line get the (basic points x point_multiplier-1). This field specifies the multiplier.- FREE_PRODUCT: How many products the customer will get for free.- UNIT_BASED_PRODUCT: How much discount (price) is given per piece of product purchased.- PRODUCT_BASED_DISCOUNT: Total discount (price) provided. Only applied to one piece of the line item.- PRODUCT_BASED_PERCENTAGE: How much discount (percentage) is provided. Only applied to one piece of the line item.- UNIT_BASED_PERCENTAGE: How much discount (percentage) is given per piece of product purchased.- FIX_DISCOUNT: How much discount (price) is given. Fix value discount on the line item. The total value of the line item must be larger than or equal to the value of the FIX_DISCOUNT.Example: 100.5 |
| offerRewardRule.rounding | String | Enum values: - DOWN- UP- MATH |
Yes | See rewardIncrement.Example: UP |
| offerRewardRule.ruleType | String | Enum values: - FREE_PRODUCT- FIX_DISCOUNT- UNIT_BASED_DISCOUNT- UNIT_BASED_PERCENTAGE- PRODUCT_BASED_DISCOUNT- PRODUCT_BASED_PERCENTAGE- FIX_POINTS- POINTS_MULTIPLIER- VISIT_BOOST- GAME_INVITATION |
No | Type of discount. See table for the possible values for each offerType.Example: FREE_PRODUCT |
| offerSubtype | String | Enum value: - GIVEAWAY |
Yes | Offer sub-type should be GIVEAWAY for all the offers which need to be reimbursed to the retailers (discount/free product), dependent on the reimbursement set up in the given country. Does not drive any offer-related functionalities. Failing to select offer sub-type as a giveaway can prevent retailers from being reimbursed through GSAP, please check your setup.Example: GIVEAWAY |
| offerTitle | Array of objects | N/A | No | The title of the offer for each language |
| offerTitle.language | String | 2 characters | No | The language of the offer’s title. Example: en |
| offerTitle.text | String | Max length is 200 characters. |
No | The title. Example: 10% discount on Shell Helix |
| offerType | String | Enum values: - BASIC_MASS- CONDITIONAL- GAME_MASS- GFR_COUNTER- GFR_SURPRISE- GOODWILL- PARTNER_BMO- PARTNER_SURPRISE- POINT_CONDITIONAL- POWER_UP- SEASONAL_BASIC_MASS- STAMP_COUNTER- STAMP_SURPRISE- SURPRISE- TARGETED_BASIC_MASS- TARGETED_GAME_MASS- TARGETED_GFR_COUNTER- TARGETED_SEASONAL_BASIC_MASS- VISIT_BOOST- WELCOME |
No | Type of the offer. Example: BASIC_MASS |
| partialRewardOffer | Boolean | true / false |
Yes | Defines whether reward can be split up over multiple transactions. Example: false |
| partnerCode | String | Max length is 12 characters. |
No, when offerType is:- PARTNER_BMO- PARTNER_SURPRISEYes, for other offerType. |
Defines the specific Partner. Used for Partner offers. Must exist in loyalty management. Example: RAC |
| partnerFundingPercentage | Number (double) | Max is 100.0. |
- No, when partnerCode is not empty and offerRewardRule.ruleType is not FIX_POINTS or POINTS_MULTIPLIER.- No, when previous condition is false and offerType is:- PARTNER_BMO- PARTNER_SUPRISE- Yes, for other cases. |
For partner offers it gives the percentage that the partner pays of the discount amount. Not processed in point-based offers (where offerRewardRule.ruleType is either FIX_POINTS or POINTS_MULTIPLIER).Example: 12.5 |
| partnerPointsValue | Number (double) | N/A | No, when partnerCode is not empty and offerRewardRule.ruleType is FIX_POINTS or POINTS_MULTIPLIER.Yes, for other cases. |
Cash value of point-based offers. Used for partner billing calculations. Usable only in point-based offers (point-based offer: offerRewardRule.ruleType is FIX_POINTS or POINTS_MULTIPLIER). Works only if the partnerCode is filled. The currency is market specific, always the main, local currency of the market (Euro, Zloty, Forint, ...)Example: 10.5 |
| qualifyingVisitTarget | Number (integer) | Max is 999999999999. |
No, when offerType is:- TARGETED_GFR_COUNTER- GFR_COUNTERYes, for other offerType. |
Number of QVs customer needs to collect to complete tracker cycle. Only used in the UK. Example: 10 |
| replacedOfferCode | Number (integer) | Max is 999999999999. |
No, when offerType = POWER_UP.Yes, for other offerType. |
Basic Mass Offer ID that needs to be boosted by the POWER_UP.Example: 100 |
| requiredStamp | Number (integer) | Max is 999999999999. |
No, when offerType is:- POWER_UP- STAMP_COUNTERYes, for other offerType. |
Number of targeted stamps to complete the cycle, Optional for TH/PH for stamp counter and targeted stamp counter. Example: 10 |
| retailSite | String | Max length is 200 characters. |
Yes | Site where the offer can be used. Example: 82dc5ab1-1ceb-5cfe-b100-8cdfa4b306a6 |
| rewardEngineExcluded | Boolean | true / false |
Yes | Defines whether offer should be excluded from ODE offer bank. Example: true |
| validityLimitation | String | Max length is 30 characters. |
Yes | To have an offer that is available only on certain date (for example: every Friday; every day between 3-4PM; until 15 May). Example: Every Friday |
| validityStartOffset | Number (integer) | Min is 1. Max is 999999999999. |
No, when offerType is:GFR_SURPRISE- STAMP_COUNTER- STAMP_SURPRISEYes, for other offerType. |
Defines number of days when the reward will be assigned after the cycle is completed. Example: 15 |
| visibleFrom | Date | Date Format should be YYYY-MM-DD. |
Yes | Date from which the offer will be visible in frontend apps. Example: 2023-12-01 |
Availability of reward rule types by each offer type
| Offer Type by Reward Rule Type | FREE_PRODUCT | FIX_DISCOUNT | UNIT_BASED_DISCOUNT | UNIT_BASED_PERCENTAGE | PRODUCT_BASED_DISCOUNT | PRODUCT_BASED_PERCENTAGE | FIX_POINTS | POINTS_MULTIPLIER | VISIT_BOOST | GAME_INVITATION |
|---|---|---|---|---|---|---|---|---|---|---|
| BASIC_MASS | N/A | X | X | X | N/A | N/A | X | X | N/A | N/A |
| TARGETED_BASIC_MASS | X | X | X | X | X | X | N/A | X | N/A | N/A |
| SEASONAL_BASIC_MASS | X | X | X | X | X | X | N/A | X | N/A | N/A |
| TARGETED_SEASONAL_BASIC_MASS | X | X | X | X | X | X | N/A | X | N/A | N/A |
| CONDITIONAL | X | X | X | X | X | X | X | X | N/A | N/A |
| SURPRISE | X | X | X | X | X | X | X | X | N/A | N/A |
| GOODWILL | X | X | X | X | X | X | N/A | N/A | N/A | N/A |
| STAMP_SURPRISE | X | X | X | X | X | X | N/A | N/A | N/A | N/A |
| GFR_SURPRISE | N/A | X | X | X | X | X | N/A | N/A | N/A | N/A |
| VISIT_BOOST | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | X | N/A |
| PARTNER_BMO | X | X | X | X | X | X | N/A | N/A | N/A | N/A |
| PARTNER_SURPRISE | X | X | X | X | X | X | X | N/A | N/A | N/A |
| WELCOME | X | X | X | X | X | X | X | X | N/A | N/A |
| POINT_CONDITIONAL | X | X | X | X | X | X | X | X | N/A | N/A |
| TARGETED_GAME_MASS | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | X |
| GAME_MASS | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | X |
| POWER_UP | N/A | N/A | X | X | X | X | N/A | N/A | N/A | N/A |
Sample request
curl --location 'https://offermanagementapis-qa.azurewebsites.net/api/v1/offers/submit' \
--header 'Authorization: Bearer ***' \
--header 'countryCode: GB' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data '{
"acceptanceRequired": true,
"accumulative": false,
"assignableFrom": "2023-12-01",
"assignableTo": "2023-12-02",
"costOfReward": 12.25,
"customText": [
{
"language": "en",
"text": "Fill min 1L of any fuel and get 200 pts."
}
],
"deactivationAllowed": true,
"displayOrder": 20,
"expirationDays": 30,
"expirationDaysAchievement": 30,
"gameDetails": {
"campaignOverviewImage": "82dc5ab1-1ceb-5cfe-b100-8cdfa4b306a6",
"gameDescription": [
{
"language": "en",
"text": "Play every day and get 200 points."
}
],
"gameIcon": "1234567890",
"gameTANDCURL": "http://www.example.com/terms",
"gameType": "Luck Game",
"gameURL": "http://www.example.com",
"inviteDurationDays": 100,
"prizeDescription": [
{
"language": "en",
"text": "This a prize description."
}
]
},
"initiallyActive": true,
"isDefault": false,
"numberOfAssign": 3,
"numberOfUsage": 0,
"offerAchievementRule": [
{
"achievementRuleType": "PRODUCT_PURCHASE",
"excludeProducts": [
"CG0000000163"
],
"includeProducts": [
"CG0000000123"
],
"label": "Rule 1",
"progressIncrement": 100,
"requiredQuantity": 50,
"requiredTransactions": 10
}
],
"offerBackground": "82dc5ab1-1ceb-5cfe-b100-8cdfa4b306a6",
"offerCode": "1234567890",
"offerDescription": [
{
"language": "en",
"text": "Fill min 1L of any fuel and get 200 pts."
}
],
"offerName": "New offer",
"offerReceiptMessage": [
{
"language": "en",
"text": "Fill min 1L of any fuel and get 200 pts"
}
],
"offerResetDay": 12,
"offerRewardConditionRule": [
{
"conditionRuleType": "SPENT_AMOUNT",
"productCode": "CG0000000163",
"requiredValue": 12.5
}
],
"offerRewardRule": {
"productCode": "CG0000000163",
"rewardIncrement": 1000,
"rewardLimit": 1000.5,
"rewardValue": 100.5,
"rounding": "UP",
"ruleType": "FREE_PRODUCT"
},
"offerSubType": "GIVEAWAY",
"offerTitle": [
{
"language": "en",
"text": "10% discount on Shell Helix"
}
],
"offerType": "BASIC_MASS",
"partialRewardOffer": false,
"partnerCode": "RAC",
"partnerFundingPercentage": 12.5,
"partnerPointsValue": 10.5,
"qualifyingVisitTarget": 10,
"replacedOfferCode": 100,
"requiredStamp": 10,
"retailSite": "82dc5ab1-1ceb-5cfe-b100-8cdfa4b306a6",
"rewardEngineExcluded": true,
"validityLimitation": "Every Friday",
"validityStartOffset": 15,
"visibleFrom": "2023-12-01"
}'
After creating the offer, the offer will be sent to LOD. When LOD has processed it, the offer will be sent to Adobe.
Response
On success the response will have a 201 Created status and the body of the response will contain a simple JSON object with:
| KEY | NULLABLE | VALUE TYPE | DESCRIPTION |
|---|---|---|---|
| offerCode | No | String | Code of the new offer. |
| offerId | No | String | Unique identifier of the new offer. |
| status | No | String | Status of the new offer. Can be one of the following values: - Draft- Approved- Sent to loyalty- Loaded to loyalty- Failed to load in loyalty- Loaded to campaign- Failed to load in campaign- Expired |
Sample Response
{
"offerCode": "test",
"offerId": 12,
"status": "Draft"
}
Exception Handling
The format of errors is always the same and specified in the Fundamentals section. For this endpoint, this is the list of possible errors:
| HTTP CODE | Description | Scenarios/Use case |
|---|---|---|
| 400 | Bad Request | Json format is not valid. |
| 401 | Unauthorized | The user token is not valid anymore or missing. |
| 403 | Forbidden | The user does not have permissions to do this action. |
| 422 | Unprocessable Content | Mandatory fields are missing. |
Assign an offer to a customer
This endpoint of the Offer Submission API https://offermanagementapis-qa.azurewebsites.net/api/v1/offers/{offerId}/assign uses the HTTP POST method.
Headers parameters
| HEADER PARAMETER | DATA TYPE | LIMITS (MIN/MAX) | NULLABLE | DESCRIPTION |
|---|---|---|---|---|
| Authorization | String | N/A | No | This is a Bearer token. It should be the JWT token you got when you requested an Access Token before. Example: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c |
Path parameters
| PATH PARAMETER | DATA TYPE | LIMITS (MIN/MAX) | NULLABLE | DESCRIPTION |
|---|---|---|---|---|
| offerId | Number (integer) | N/A | No | This is the offer id you want to assign to a customer. Example: 123 |
Request body parameters
| REQUEST BODY PARAMETER | DATA TYPE | LIMITS (MIN/MAX) | NULLABLE | DESCRIPTION |
|---|---|---|---|---|
| consumerUUID | String | N/A | No | The consumer you want to assign the offer. Example: 942a1fb4-d487-454c-9c1c-aee920c420fb |
| validFrom | DateTime | Cannot be a past date. | No | Offer validity start date in JSON recommended format: yyyy-MM-ddTHH:mm:ssZ. The date format must follow ISO_8601.It is the date from which the offer becomes available to the customer. Example: 2023-08-24T14:15:22Z |
| validTo | DateTime | Cannot be a date before validFrom. |
No, when validityPeriod=0.Yes, if validityPeriod!=0. |
Offer validity start date in JSON recommended format: yyyy-MM-ddTHH:mm:ssZ. The date format must follow ISO_8601.It is the date until which the offer is available to the customer. Example: 2023-12-24T14:15:22Z |
| validityPeriod | Number (integer) | N/A | No, when validTo is null.Yes, if validTo is not null. |
This is the number of days for which the assignment is valid after validFrom. It's optional if validTo is set and required otherwise. If not set, LOD will receive the default value of 0. validTo is calculating adding this value to the validFrom date.If both validTo and validityPeriod are present, validityPeriod has priority over validTo.Example: 31 |
Sample Request
curl --location 'https://offermanagementapis-qa.azurewebsites.net/api/v1/offers/123/assign' \
--header 'Authorization: Bearer ***' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data '{
"consumerUUID": "942a1fb4-d487-454c-9c1c-aee920c420fb",
"validFrom": "2023-08-24T14:15:22Z",
"validTo": "2023-12-24T14:15:22Z",
"validityPeriod": 31
}'
Response
On success the response will have a 200 OK status and the body of the response will contain a simple JSON object with:
| KEY | NULLABLE | VALUE TYPE | DESCRIPTION |
|---|---|---|---|
| consumerUUUID | No | String | The unique identifier of the consumer. |
| description | No | String | Description of the offer. |
| offerID | No | Number (integer) | The id of the offer. |
| referenceID | No | String | The unique identifier of the offer. |
| responseCode | No | Number (integer) | The response code from LOD. 200 if the offer was assigned inmediately. 202 if LOD is using an internal async process to assign it. |
| title | No | String | The title of the offer. |
| validFrom | No | DateTime | The date and time from which the offer becomes available to the customer. |
| validTo | No | DateTime | The date and time until which the offer is available to the customer. |
Sample Response
{
"consumerUUID": "01bbf258-04f1-4ffc-be07-09a5ad5849de",
"description": "",
"offerID": 123,
"referenceID": "85f09c39-8a5b-4f22-9a1e-d89656e6017c",
"responseCode": 200,
"title": "Offer",
"validFrom": "2019-08-24T14:15:22Z",
"validTo": "2019-08-24T14:15:22Z"
}
Exception Handling
The format of errors is always the same and specified in the Fundamentals section. For this endpoint, this is the list of errors:
| HTTP CODE | Description | Scenarios/Use case |
|---|---|---|
| 400 | Bad Request | Json format is not valid. |
| 401 | Unauthorized | The user token is not valid anymore or missing. |
| 403 | Forbidden | The user does not have permissions to do this action. |
| 404 | Not found | The offer was not found using the offerId provided. |
| 422 | Unprocessable Content | Mandatory fields are missing. |
