Basket Offer Flows
This document provides a detailed explanation of the basket offer flows, including the purpose of the flow, the services involved, and the description of each field in the requests and responses.
Purpose of the Flow
The Basket Offer Flow is designed to integrate with third-party systems to retrieve and apply discount offers to a customer's shopping basket. This flow ensures that the basket's current state, including its items and any existing discounts, is sent to the third-party system. The third-party system evaluates the basket and returns applicable offers, which are then applied to the basket before proceeding to the payment stage. This flow is particularly useful for:
- Dynamic Discount Calculation: Allowing third-party systems to calculate discounts based on the basket's contents.
- Custom Promotions: Supporting external promotion engines to provide tailored offers.
- Scalability: Standardizing the integration with multiple third-party systems using a consistent API pattern.
This part of the document contains the list of services that can be integrated in flows above. 2 configuration parameters will be shared during integration:
Field | Description |
---|---|
username | Username for basic authentication |
password | Password for basic authentication |
basket-offers (POST)
This service is used to retrieve discount offers for a customer's basket from a third-party system. It sends the current state of the basket and user information to the third-party system and receives applicable offers in response.
URL:
^^/offers
Request Headers
Header | Description | Requirement |
---|---|---|
x-akinon-request-id | Unique ID for problem solving & tracing. | Mandatory |
x-akinon-api-version | Akinon Customer API version. | Mandatory |
Authorization | Basic [BASE64_encoded(username:password)] | Mandatory |
Request Body raw (json)
{
"basket": {
"id": 0, // Unique identifier for the basket.
"version": 0, // Version of the basket to ensure consistency.
"basketItems": [
{
"id": 0, // Unique identifier for the basket item.
"unitPrice": 0.0, // Price per unit of the item.
"quantity": 0, // Quantity of the item in the basket.
"unitType": "", // Type of unit (e.g., QUANTITY, KILOGRAM)
"taxRate": 0.0, // Tax rate applied to the item.
"totalAmount": 0.0, // Total price of the item (unitPrice * quantity).
"discountAmount": 0.0, // Total discount applied to the item.
"consumedQuantity": 0, // Quantity consumed for discounts.
"globallyConsumedQuantity": 0, // Quantity consumed globally for discounts.
"currencyType": "TRY", // https://en.wikipedia.org/wiki/ISO_4217
"appliedDiscounts": [
{
"discount":{
"type":"", //Type of discount (LOYALTY_POINT, SAMPLE_PRODUCT, DEFERRED, POINT, SHIPPING, BASKET)
"description":"", // Description of the discount.
"discountedBasketItems":[ // Items affected by the discount.
{
"pk": 0,
"quantity": 0
}
],
"conditionConsumedBasketItems":[ // Items consumed to meet discount conditions.
{
"pk": 0,
"consumedQuantity": 0,
"globallyConsumedQuantity": 0
}
],
"extraArgs":[ // Additional arguments for the discount. Details at below
// DiscountObjects ExtraArgs
]
}
}
],
"product": {
"id": 0, // Unique identifier for the product.
"sku": "", // Stock Keeping Unit of the product.
"name": "", // Name of the product.
"attributes": [ // Additional attributes of the product.
{
"categoryId": "", // Category id of the product.
"variantId": "" // Variant id of the product.
}
]
}
}
]
},
"user": {
"emailAllowed":true, // Whether the user allows email communication.
"smsAllowed":true, // Whether the user allows SMS communication.
"callAllowed":true, // Whether the user allows phone calls.
"phone":"", // User's phone number.
"email": [""] // List of user's email addresses.
}
}
Discount Types Extra Args
The following discount types and their associated extra arguments are supported:
Loyalty Point
[
"loyaltyData":{
"amount":0.00, // Amount of loyalty points used.
"benefitCoefficient":"", // Coefficient for calculating benefits.
"validFrom":"", // Start date of the loyalty points.
"validUntil":"" // Expiration date of the loyalty points.
}
]
Sample Product
[
"sampleProducts":[
{
"id": 0 // Unique identifier for the sample product.
}
],
"allowedQuantity":0 // Maximum quantity allowed for the sample product.
]
Deferred
[
"data":{
"coupon":"" // Coupon code for the deferred discount.
}
]
Point
[]
Shipping
[]
Basket
[
"discount":0.00 // Total discount applied to the basket.
]
Request Body (typescript interface)
interface BasketOffersRequest {
basket: Basket;
user: User;
}
interface Basket {
id: number;
version: number;
basketItems: BasketItem[];
}
interface BasketItem {
id: number;
unitPrice: number;
quantity: number;
unitType: string;
taxRate: number;
totalAmount: number;
discountAmount: number;
consumedQuantity: number;
globallyConsumedQuantity: number;
currencyType: string;
appliedDiscounts: AppliedDiscount[];
product: Product;
}
interface AppliedDiscount {
discount: Discount;
}
interface BaseDiscount {
description: string;
discountedBasketItems: DiscountedBasketItem[];
conditionConsumedBasketItems: ConditionConsumedBasketItem[];
}
type Discount =
| (BaseDiscount & { type: 'LOYALTY_POINT'; extraArgs: LoyaltyPointArgs })
| (BaseDiscount & { type: 'SAMPLE_PRODUCT'; extraArgs: SampleProductArgs })
| (BaseDiscount & { type: 'DEFERRED'; extraArgs: DeferredArgs })
| (BaseDiscount & { type: 'POINT'; extraArgs?: undefined })
| (BaseDiscount & { type: 'SHIPPING'; extraArgs?: undefined })
| (BaseDiscount & { type: 'BASKET'; extraArgs: BasketArgs });
interface LoyaltyPointArgs {
loyaltyData: {
amount: number;
benefitCoefficient: string;
validFrom: string;
validUntil: string;
};
}
interface SampleProductArgs {
sampleProducts: {
id: number;
}[];
allowedQuantity: number;
}
interface DeferredArgs {
data: {
coupon: string;
};
}
interface BasketArgs {
discount: number;
}
interface DiscountedBasketItem {
pk: number;
quantity: number;
}
interface ConditionConsumedBasketItem {
pk: number;
consumedQuantity: number;
globallyConsumedQuantity: number;
}
interface Product {
id: number;
sku: string;
name: string;
attributes: ProductAttribute[];
}
interface ProductAttribute {
categoryId: string;
variantId: string;
}
interface User {
emailAllowed: boolean;
smsAllowed: boolean;
callAllowed: boolean;
phone: string;
email: string[];
}
Response Body raw 200 (json)
[ // list of offers
{
"notifyAfterOrderCreation": true, // Indicates if the offer requires notification(basket-offers-used service) after order creation.
"discount":{
"id": "", // Unique identifier for the discount.
"type":"", // Type of discount (LOYALTY_POINT, SAMPLE_PRODUCT, DEFERRED, POINT, SHIPPING, BASKET).
"description":"", // Description of the discount.
"discountedBasketItems":[
{
"pk": 0, // Primary key of the basket item.
"quantity": 0 // Quantity of the item affected by the discount.
}
],
"conditionConsumedBasketItems":[
{
"pk": 0, // Primary key of the basket item consumed for the discount.
"consumedQuantity": 0, // Quantity consumed for the discount.
"globallyConsumedQuantity": 0 // Quantity consumed globally for the discount.
}
],
"extraArgs":{ // Additional arguments for the discount.
// DiscountObjects ExtraArgs
}
},
"priority": 0, // Priority of the discount.
"label": "", // Label for the discount
"isMergeable":true, // Indicates if the discount can be combined with other discounts.
"successMessage":"", // Message displayed when the discount is successfully applied.
"upsellMessage":"" // Message encouraging the user to take further actions (e.g., add more items).
}
]
Response Body (typescript interface)
type BasketOffersResponse = BasketOffer[];
interface BasketOffer {
notifyAfterOrderCreation: boolean;
discount: ResponseDiscount;
priority: number;
label: string;
isMergeable: boolean;
successMessage: string;
upsellMessage: string;
}
interface ResponseDiscount {
id: string;
type: DiscountType;
description: string;
discountedBasketItems: DiscountedBasketItem[];
conditionConsumedBasketItems: ConditionConsumedBasketItem[];
extraArgs?: Record<string, unknown>;
}
basket-offers-used (POST)
This service is used to notify the system about the discounts that were applied to the basket. It ensures that the third-party system is informed about the usage of the offers.
URL:
^^/use-offers
Request Headers
Header | Description | Requirement |
---|---|---|
x-akinon-request-id | Unique ID for problem solving & tracing. | Mandatory |
x-akinon-api-version | Akinon Customer API version. | Mandatory |
Authorization | Basic [BASE64_encoded(username:password)] | Mandatory |
Request Body raw (json)
{
"basket": { // Final state of the basket
"id": 0, // Unique identifier for the basket.
"version": 0, // Version of the basket to ensure consistency.
"basketItems": [
{
"id": 0, // Unique identifier for the basket item.
"unitPrice": 0.0, // Price per unit of the item.
"quantity": 0, // Quantity of the item in the basket.
"unitType": "", // Type of unit (e.g., QUANTITY, KILOGRAM)
"taxRate": 0.0, // Tax rate applied to the item.
"totalAmount": 0.0, // Total price of the item (unitPrice * quantity).
"discountAmount": 0.0, // Total discount applied to the item.
"consumedQuantity": 0, // Quantity consumed for discounts.
"globallyConsumedQuantity": 0, // Quantity consumed globally for discounts.
"currencyType": "TRY", // https://en.wikipedia.org/wiki/ISO_4217
"appliedDiscounts": [
{
"discount":{
"type":"", //Type of discount (LOYALTY_POINT, SAMPLE_PRODUCT, DEFERRED, POINT, SHIPPING, BASKET)
"description":"", // Description of the discount.
"discountedBasketItems":[ // Items affected by the discount.
{
"pk": 0,
"quantity": 0
}
],
"conditionConsumedBasketItems":[ // Items consumed to meet discount conditions.
{
"pk": 0,
"consumedQuantity": 0,
"globallyConsumedQuantity": 0
}
],
"extraArgs":[ // Additional arguments for the discount. See below
// DiscountObjects ExtraArgs
]
}
}
],
"product": {
"id": 0, // Unique identifier for the product.
"sku": "", // Stock Keeping Unit of the product.
"name": "", // Name of the product.
"attributes": [ // Additional attributes of the product.
{
"categoryId": "", // Category id of the product.
"variantId": "" // Variant id of the product.
}
]
}
}
]
},
"usedDiscounts": [
"" // Unique identifier for a used discount.
]
}
Request Body (typescript interface)
interface BasketOffersUsedRequest {
basket: Basket;
usedDiscounts: string[]; // Used discount IDs
}
interface Basket {
id: number;
version: number;
basketItems: BasketItem[];
}
interface BasketItem {
id: number;
unitPrice: number;
quantity: number;
unitType: string;
taxRate: number;
totalAmount: number;
discountAmount: number;
consumedQuantity: number;
globallyConsumedQuantity: number;
currencyType: string;
appliedDiscounts: AppliedDiscount[];
product: Product;
}
interface AppliedDiscount {
discount: Discount;
}
interface BaseDiscount {
description: string;
discountedBasketItems: DiscountedBasketItem[];
conditionConsumedBasketItems: ConditionConsumedBasketItem[];
}
type Discount =
| (BaseDiscount & { type: 'LOYALTY_POINT'; extraArgs: LoyaltyPointArgs })
| (BaseDiscount & { type: 'SAMPLE_PRODUCT'; extraArgs: SampleProductArgs })
| (BaseDiscount & { type: 'DEFERRED'; extraArgs: DeferredArgs })
| (BaseDiscount & { type: 'POINT'; extraArgs?: undefined })
| (BaseDiscount & { type: 'SHIPPING'; extraArgs?: undefined })
| (BaseDiscount & { type: 'BASKET'; extraArgs: BasketArgs });
interface LoyaltyPointArgs {
loyaltyData: {
amount: number;
benefitCoefficient: string;
validFrom: string;
validUntil: string;
};
}
interface SampleProductArgs {
sampleProducts: {
id: number;
}[];
allowedQuantity: number;
}
interface DeferredArgs {
data: {
coupon: string;
};
}
interface BasketArgs {
discount: number;
}
interface DiscountedBasketItem {
pk: number;
quantity: number;
}
interface ConditionConsumedBasketItem {
pk: number;
consumedQuantity: number;
globallyConsumedQuantity: number;
}
interface Product {
id: number;
sku: string;
name: string;
attributes: ProductAttribute[];
}
interface ProductAttribute {
categoryId: string;
variantId: string;
}
interface User {
emailAllowed: boolean;
smsAllowed: boolean;
callAllowed: boolean;
phone: string;
email: string[];
}
Response Body raw 200
(no body)
Response Body For Errors (ALL)
If any errors are encountered in the services, these errors should be reported in the format below, and the list of error codes should be shared with Akinon.
Response Body raw 4xx/5xx (json)
{
"errors": [
{
"code": "",
"field": "",
"message": ""
}
]
}
Response Body raw 4xx/5xx (typescript interface)
interface ErrorResponse {
errors: ErrorItem[];
}
interface ErrorItem {
code: string;
field: string;
message: string;
}