# 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.

{% hint style="warning" %}
The request and response structures described in this document are for API version v2. In version v1, the structures were different. To use the v2 structure (either by migrating from v1 or for new integrations), you must set `"api_version": "v2"` in your PromotionGateway configuration.
{% endhint %}

**Example configuration:**

```json
{
  "auth": {
    "password": "xx",
    "username": "xxx"
  },
  "urls": {
    "base_url": "xxx",
    "query_offers": "xxx"
  },
  "klass": "omnishop.promotions.backend.extension.service.ExtensionService",
  "api_version": "v2"
}
```

## <mark style="color:red;">Purpose of the Flow</mark>

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 |

## <mark style="color:red;">basket-offers (POST)</mark>

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   |
| x-app-device            | Client/session type (e.g. `default`, `android`, `instore`). | Mandatory   |
| x-store-id              | Store identifier (when available).                          | Optional    |
| x-store-remote-id       | Remote store identifier (when available).                   | Optional    |
| x-store-staff-id        | Staff user identifier (when available).                     | Optional    |
| x-store-staff-remote-id | Remote staff user identifier (when available).              | Optional    |
| x-store-staff-email     | Staff user email address (when available).                  | Optional    |
| Authorization           | Basic \[BASE64\_encoded(username:password)]                 | Mandatory   |

**Request Body Structure**

<table><thead><tr><th width="261.890625">Field</th><th width="87.31640625">Type</th><th>Description</th></tr></thead><tbody><tr><td>basket</td><td>Object</td><td>Container for basket information</td></tr><tr><td>basket.id</td><td>Number</td><td>Unique identifier for the basket</td></tr><tr><td>basket.version</td><td>Number</td><td>Version of the basket to ensure consistency</td></tr><tr><td>basket.voucherCode</td><td>String/Null</td><td>Voucher or coupon code (optional)</td></tr><tr><td>basket.basketItems</td><td>Array</td><td>List of items in the basket</td></tr><tr><td>basket.basketItems[].id</td><td>Number</td><td>Unique identifier for the basket item</td></tr><tr><td>basket.basketItems[].unitPrice</td><td>String</td><td>Price per unit of the item</td></tr><tr><td>basket.basketItems[].quantity</td><td>Number</td><td>Quantity of the item in the basket</td></tr><tr><td>basket.basketItems[].unitType</td><td>String</td><td>Type of unit (e.g., QUANTITY, KILOGRAM)</td></tr><tr><td>basket.basketItems[].taxRate</td><td>String</td><td>Tax rate applied to the item</td></tr><tr><td>basket.basketItems[].totalAmount</td><td>String</td><td>Total price of the item (unitPrice * quantity)</td></tr><tr><td>basket.basketItems[].discountAmount</td><td>String</td><td>Total discount applied to the item</td></tr><tr><td>basket.basketItems[].globallyConsumedQuantity</td><td>String</td><td>Quantity consumed globally for discounts (decimal value as string)</td></tr><tr><td>basket.basketItems[].currencyType</td><td>String</td><td>Currency code (ISO 4217)</td></tr><tr><td>basket.basketItems[].appliedDiscounts</td><td>Array</td><td>List of discounts applied to this item</td></tr><tr><td>basket.basketItems[].appliedDiscounts[].discount</td><td>Object</td><td>Discount details</td></tr><tr><td>basket.basketItems[].appliedDiscounts[].discount.type</td><td>String</td><td>Type of discount (LOYALTY_POINT, SAMPLE_PRODUCT, DEFERRED, POINT, SHIPPING, BASKET)</td></tr><tr><td>basket.basketItems[].appliedDiscounts[].discount.description</td><td>String</td><td>Description of the discount</td></tr><tr><td>basket.basketItems[].appliedDiscounts[].discount.discountedBasketItems</td><td>Array</td><td>Items to which the discount will be applied and distributed based on quantity</td></tr><tr><td>basket.basketItems[].appliedDiscounts[].discount.discountedBasketItems[].pk</td><td>Number</td><td>Primary key of the basket item</td></tr><tr><td>basket.basketItems[].appliedDiscounts[].discount.discountedBasketItems[].quantity</td><td>String</td><td>Quantity of the item affected by the discount (decimal value as string)</td></tr><tr><td>basket.basketItems[].appliedDiscounts[].discount.conditionConsumedBasketItems</td><td>Array</td><td>Items consumed to meet discount conditions; no additional items are consumed once offer conditions are satisfied</td></tr><tr><td>basket.basketItems[].appliedDiscounts[].discount.conditionConsumedBasketItems[].pk</td><td>Number</td><td>Primary key of the basket item</td></tr><tr><td>basket.basketItems[].appliedDiscounts[].discount.conditionConsumedBasketItems[].quantity</td><td>String</td><td>Quantity consumed for the discount (decimal value as string)</td></tr><tr><td>basket.basketItems[].appliedDiscounts[].discount.extraArgs</td><td>Object</td><td>Additional arguments for the discount</td></tr><tr><td>basket.basketItems[].product</td><td>Object</td><td>Product information</td></tr><tr><td>basket.basketItems[].product.id</td><td>Number</td><td>Unique identifier for the product</td></tr><tr><td>basket.basketItems[].product.sku</td><td>String</td><td>Stock Keeping Unit of the product</td></tr><tr><td>basket.basketItems[].product.name</td><td>String</td><td>Name of the product</td></tr><tr><td>basket.basketItems[].product.attributes</td><td>Object</td><td>Additional attributes of the product</td></tr><tr><td>user</td><td>Object</td><td>User information</td></tr><tr><td>user.emailAllowed</td><td>Boolean</td><td>Whether the user allows email communication</td></tr><tr><td>user.smsAllowed</td><td>Boolean</td><td>Whether the user allows SMS communication</td></tr><tr><td>user.callAllowed</td><td>Boolean</td><td>Whether the user allows phone calls</td></tr><tr><td>user.phone</td><td>String/Null</td><td>User's phone number</td></tr><tr><td>user.email</td><td>Array</td><td>List of user's email addresses</td></tr></tbody></table>

**Request Body Example**

```json
{
    "basket": {
      "id": 32,
      "version": 1758310922044282,
      "voucherCode": null,
        "basketItems": [
            {
                "id": 59,
                "unitPrice": "500.00",
                "quantity": 1,
                "unitType": "QUANTITY",
                "taxRate": "20.00",
                "totalAmount": "500.00",
                "discountAmount": "0.00",
                "globallyConsumedQuantity": "0.0",
                "currencyType": "TRY",
                "appliedDiscounts": [
                    {
                        "discount": {
                            "type": "BASKET",
                            "description": "Internal Offer",
                            "discountedBasketItems": [
                                {
                                    "pk": 59,
                                    "quantity": "1"
                                },
                                {
                                    "pk": 58,
                                    "quantity": "7"
                                }
                            ],
                            "conditionConsumedBasketItems": [
                                {
                                    "pk": 58,
                                    "quantity": "0.2"
                                }
                            ],
                            "extraArgs": {
                                "discount": "0.00"
                            },
                        }
                    }
                ],
                "product": {
                    "id": 100009,
                    "sku": "SKU8",
                    "name": "Test Product 8",
                    "attributes": {}
                }
            },
            {
                "id": 58,
                "unitPrice": "500.00",
                "quantity": 7,
                "unitType": "QUANTITY",
                "taxRate": "20.00",
                "totalAmount": "3500.00",
                "discountAmount": "12.32",
                "globallyConsumedQuantity": "0.0",
                "currencyType": "TRY",
                "appliedDiscounts": [
                    {
                        "discount": {
                            "type": "BASKET",
                            "description": "Internal Offer",
                            "discountedBasketItems": [
                                {
                                    "pk": 59,
                                    "quantity": "1"
                                },
                                {
                                    "pk": 58,
                                    "quantity": "7"
                                }
                            ],
                            "conditionConsumedBasketItems": [
                                {
                                    "pk": 58,
                                    "quantity": "0.2"
                                }
                            ],
                            "extraArgs": {
                                "discount": "12.32"
                            },
                        }
                    }
                ],
                "product": {
                    "id": 100010,
                    "sku": "SKU9",
                    "name": "Test Product 9",
                    "attributes": {}
                }
            }
        ]
    },
    "user": {
        "emailAllowed": true,
        "smsAllowed": true,
        "callAllowed": false,
        "phone": null,
        "email": []
    }
}
```

### <mark style="color:red;">**Discount Types Extra Args**</mark>

The following discount types and their associated extra arguments are supported:

#### **Loyalty Point Extra Args**

<table><thead><tr><th width="250.0703125">Field</th><th width="86.8203125">Type</th><th>Description</th></tr></thead><tbody><tr><td>loyaltyData</td><td>Object</td><td>Loyalty point information</td></tr><tr><td>loyaltyData.amount</td><td>String</td><td>Amount of loyalty points used (decimal value as string)</td></tr><tr><td>loyaltyData.benefitCoefficient</td><td>String</td><td>Coefficient for calculating benefits</td></tr><tr><td>loyaltyData.validFrom</td><td>String</td><td>Start date of the loyalty points</td></tr><tr><td>loyaltyData.validUntil</td><td>String</td><td>Expiration date of the loyalty points</td></tr></tbody></table>

```json
{
  "extraArgs": {
    "loyaltyData": {
      "amount": "50.00",
      "benefitCoefficient": "1.5",
      "validFrom": "2025-01-01",
      "validUntil": "2025-12-31"
    }
  }
}
```

#### **Sample Product Extra Args**

<table><thead><tr><th width="184.05859375">Field</th><th width="97.14453125">Type</th><th>Description</th></tr></thead><tbody><tr><td>sampleProducts</td><td>Array</td><td>List of sample products</td></tr><tr><td>sampleProducts[].id</td><td>Number</td><td>Unique identifier for the sample product</td></tr><tr><td>allowedQuantity</td><td>Number</td><td>Maximum quantity allowed for the sample product</td></tr></tbody></table>

```json
{
  "extraArgs": {
    "sampleProducts": [
      {
        "id": 12345
      },
      {
        "id": 67890
      }
    ],
    "allowedQuantity": 2
  }
}
```

#### **Deferred Extra Args**

<table><thead><tr><th width="157.98046875">Field</th><th width="129.91015625">Type</th><th>Description</th></tr></thead><tbody><tr><td>data</td><td>Object</td><td>Deferred discount data</td></tr><tr><td>data.coupon</td><td>String</td><td>Coupon code for the deferred discount</td></tr></tbody></table>

```json
{
  "extraArgs": {
    "data": {
      "coupon": "SAVE2025"
    }
  }
}
```

#### **Point Extra Args**

No additional arguments required.

```json
{
  "extraArgs": {}
}
```

#### **Shipping Extra Args**

No additional arguments required.

```json
{
  "extraArgs": {}
}
```

#### **Basket Extra Args**

<table><thead><tr><th width="101.16796875">Field</th><th width="93.4609375">Type</th><th>Description</th></tr></thead><tbody><tr><td>discount</td><td>String</td><td>Total discount applied to the basket (decimal value as string)</td></tr></tbody></table>

```json
{
  "extraArgs": {
    "discount": "25.50"
  }
}
```

**Request Body (typescript interface)**

```ts
interface BasketOffersRequest {
  basket: Basket;
  user: User;
}

interface Basket {
  id: number;
  version: number;
  voucherCode: string | null;
  basketItems: BasketItem[];
}

interface BasketItem {
  id: number;
  unitPrice: string;
  quantity: number;
  unitType: string;
  taxRate: string;
  totalAmount: string;
  discountAmount: string;
  globallyConsumedQuantity: string;
  currencyType: string;
  appliedDiscounts: AppliedDiscount[];
  product: Product;
}

interface AppliedDiscount {
  discount: Discount;
}

interface BaseDiscount {
  type: 'LOYALTY_POINT' | 'SAMPLE_PRODUCT' | 'DEFERRED' | 'POINT' | 'SHIPPING' | 'BASKET';
  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: string;
    benefitCoefficient: string;
    validFrom: string; 
    validUntil: string;
  };
}

interface SampleProductArgs {
  sampleProducts: {
    id: number;
  }[];
  allowedQuantity: number;
}

interface DeferredArgs {
  data: {
    coupon: string;
  };
}

interface BasketArgs {
  discount: string;
}

interface DiscountedBasketItem {
  pk: number;
  quantity: string;
}

interface ConditionConsumedBasketItem {
  pk: number;
  quantity: string;
}

interface Product {
  id: number;
  sku: string;
  name: string;
  attributes: Record<string, any>;
}

interface User {
  emailAllowed: boolean;
  smsAllowed: boolean;
  callAllowed: boolean;
  phone: string | null;
  email: string[];
}

```

**Response Body Structure**

<table><thead><tr><th width="225.6328125">Field</th><th width="97.18359375">Type</th><th>Description</th></tr></thead><tbody><tr><td>[]</td><td>Array</td><td>List of available offers</td></tr><tr><td>[].notifyAfterOrderCreation</td><td>Boolean</td><td>Indicates if the offer requires notification after order creation</td></tr><tr><td>[].discount</td><td>Object</td><td>Discount details</td></tr><tr><td>[].discount.id</td><td>String</td><td>Unique identifier for the discount</td></tr><tr><td>[].discount.type</td><td>String</td><td>Type of discount (LOYALTY_POINT, SAMPLE_PRODUCT, DEFERRED, POINT, SHIPPING, BASKET)</td></tr><tr><td>[].discount.description</td><td>String</td><td>Description of the discount</td></tr><tr><td>[].discount.discountedBasketItems</td><td>Array</td><td>Items to which the discount will be applied and distributed based on quantity</td></tr><tr><td>[].discount.discountedBasketItems[].pk</td><td>Number</td><td>Primary key of the basket item</td></tr><tr><td>[].discount.discountedBasketItems[].quantity</td><td>Number</td><td>Quantity of the item affected by the discount</td></tr><tr><td>[].discount.conditionConsumedBasketItems</td><td>Array</td><td>Items consumed for the discount condition</td></tr><tr><td>[].discount.conditionConsumedBasketItems[].pk</td><td>Number</td><td>Primary key of the basket item consumed for the discount</td></tr><tr><td>[].discount.conditionConsumedBasketItems[].quantity</td><td>Number</td><td>Quantity consumed for the discount</td></tr><tr><td>[].discount.extraArgs</td><td>Object</td><td>Additional arguments for the discount</td></tr><tr><td>[].priority</td><td>Number</td><td>Priority of the discount</td></tr><tr><td>[].label</td><td>String</td><td>Label for the discount</td></tr><tr><td>[].isMergeable</td><td>Boolean</td><td>Indicates if the discount can be combined with other discounts</td></tr><tr><td>[].successMessage</td><td>String</td><td>Message displayed when the discount is successfully applied</td></tr><tr><td>[].upsellMessage</td><td>String</td><td>Message encouraging the user to take further actions</td></tr></tbody></table>

**Response Body Example**

```json
[
    {
        "successMessage": "Congratulations! You saved 25.50 TRY with our Spring Sale promotion.",
        "upsellMessage": "Add 2 more items to your cart and get free shipping!",
        "label": "Spring Sale - 15% Off",
        "priority": 1,
        "discount": {
            "description": "Spring Sale 2025 - 15% Off on Fashion Items",
            "discountedBasketItems": [
                {
                    "pk": 58,
                    "quantity": "1"
                }
            ],
            "extraArgs": {
                "discount": "25.50"
            },
            "conditionConsumedBasketItems": [
                {
                    "pk": 58,
                    "quantity": "1"
                }
            ],
            "type": "BASKET",
            "id": "v2-spring-discount-2025"
        },
        "notifyAfterOrderCreation": false,
        "isMergeable": true
    },
    {
        "successMessage": "Thank you for being a loyal customer! You saved 10 TRY with your member discount.",
        "upsellMessage": "Add 2 more items to your cart and get free shipping!",
        "label": "Loyalty Reward - 10 TRY Off",
        "priority": 2,
        "discount": {
            "description": "Loyalty Member Special Discount",
            "discountedBasketItems": [
                {
                    "pk": 59,
                    "quantity": "1"
                }
            ],
            "extraArgs": {
                "discount": "10.00"
            },
            "conditionConsumedBasketItems": [
                {
                    "pk": 59,
                    "quantity": "1"
                }
            ],
            "type": "BASKET",
            "id": "v2-loyalty-reward-2025"
        },
        "notifyAfterOrderCreation": true,
        "isMergeable": true
    }
]
```

**Response Body (typescript interface)**

```ts
type BasketOffersResponse = BasketOffer[];

interface BasketOffer {
  notifyAfterOrderCreation: boolean;
  discount: ResponseDiscount;
  priority: number;
  label: string;
  isMergeable: boolean;
  successMessage: string;
  upsellMessage: string;
}

interface ResponseDiscount {
  id: string;
  type: 'LOYALTY_POINT' | 'SAMPLE_PRODUCT' | 'DEFERRED' | 'POINT' | 'SHIPPING' | 'BASKET';
  description: string;
  discountedBasketItems: ResponseDiscountedBasketItem[];
  conditionConsumedBasketItems: ResponseConditionConsumedBasketItem[];
  extraArgs?: Record<string, any>;
}

interface ResponseDiscountedBasketItem {
  pk: number;
  quantity: string;
}

interface ResponseConditionConsumedBasketItem {
  pk: number;
  quantity: string;
}


```

## <mark style="color:red;">basket-offers-used (POST)</mark>

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**

<table><thead><tr><th width="182.23828125">Header</th><th width="379.40234375">Description</th><th>Requirement</th></tr></thead><tbody><tr><td>x-akinon-request-id</td><td>Unique ID for problem solving &#x26; tracing.</td><td>Mandatory</td></tr><tr><td>x-akinon-api-version</td><td>Akinon Customer API version.</td><td>Mandatory</td></tr><tr><td>x-app-device</td><td>Client/session type (e.g. <code>default</code>, <code>android</code>, <code>instore</code>).</td><td>Mandatory</td></tr><tr><td>x-store-id</td><td>Store identifier (when available).</td><td>Optional</td></tr><tr><td>x-store-remote-id</td><td>Remote store identifier (when available).</td><td>Optional</td></tr><tr><td>x-store-staff-id</td><td>Staff user identifier (when available).</td><td>Optional</td></tr><tr><td>x-store-staff-remote-id</td><td>Remote staff user identifier (when available).</td><td>Optional</td></tr><tr><td>x-store-staff-email</td><td>Staff user email address (when available).</td><td>Optional</td></tr><tr><td>Authorization</td><td>Basic [BASE64_encoded(username:password)]</td><td>Mandatory</td></tr></tbody></table>

**Request Body Structure**

<table><thead><tr><th width="269.265625">Field</th><th width="94.2734375">Type</th><th>Description</th></tr></thead><tbody><tr><td>basket</td><td>Object</td><td>Final state of the basket</td></tr><tr><td>basket.id</td><td>Number</td><td>Unique identifier for the basket</td></tr><tr><td>basket.version</td><td>Number</td><td>Version of the basket to ensure consistency</td></tr><tr><td>basket.voucherCode</td><td>String/Null</td><td>Voucher or coupon code (optional)</td></tr><tr><td>basket.basketItems</td><td>Array</td><td>List of items in the basket</td></tr><tr><td>basket.basketItems[].id</td><td>Number</td><td>Unique identifier for the basket item</td></tr><tr><td>basket.basketItems[].unitPrice</td><td>String</td><td>Price per unit of the item</td></tr><tr><td>basket.basketItems[].quantity</td><td>Number</td><td>Quantity of the item in the basket</td></tr><tr><td>basket.basketItems[].unitType</td><td>String</td><td>Type of unit (e.g., QUANTITY, KILOGRAM)</td></tr><tr><td>basket.basketItems[].taxRate</td><td>String</td><td>Tax rate applied to the item</td></tr><tr><td>basket.basketItems[].totalAmount</td><td>String</td><td>Total price of the item (unitPrice * quantity)</td></tr><tr><td>basket.basketItems[].discountAmount</td><td>String</td><td>Total discount applied to the item</td></tr><tr><td>basket.basketItems[].globallyConsumedQuantity</td><td>String</td><td>Quantity consumed globally for discounts (decimal value as string)</td></tr><tr><td>basket.basketItems[].currencyType</td><td>String</td><td>Currency code (ISO 4217)</td></tr><tr><td>basket.basketItems[].appliedDiscounts</td><td>Array</td><td>List of discounts applied to this item</td></tr><tr><td>basket.basketItems[].appliedDiscounts[].discount</td><td>Object</td><td>Discount details</td></tr><tr><td>basket.basketItems[].appliedDiscounts[].discount.type</td><td>String</td><td>Type of discount (LOYALTY_POINT, SAMPLE_PRODUCT, DEFERRED, POINT, SHIPPING, BASKET)</td></tr><tr><td>basket.basketItems[].appliedDiscounts[].discount.description</td><td>String</td><td>Description of the discount</td></tr><tr><td>basket.basketItems[].appliedDiscounts[].discount.discountedBasketItems</td><td>Array</td><td>Items to which the discount will be applied and distributed based on quantity</td></tr><tr><td>basket.basketItems[].appliedDiscounts[].discount.discountedBasketItems[].pk</td><td>Number</td><td>Primary key of the basket item</td></tr><tr><td>basket.basketItems[].appliedDiscounts[].discount.discountedBasketItems[].quantity</td><td>String</td><td>Quantity of the item affected by the discount</td></tr><tr><td>basket.basketItems[].appliedDiscounts[].discount.conditionConsumedBasketItems</td><td>Array</td><td>Items consumed to meet discount conditions; no additional items are consumed once offer conditions are satisfied</td></tr><tr><td>basket.basketItems[].appliedDiscounts[].discount.conditionConsumedBasketItems[].pk</td><td>Number</td><td>Primary key of the basket item</td></tr><tr><td>basket.basketItems[].appliedDiscounts[].discount.conditionConsumedBasketItems[].quantity</td><td>String</td><td>Quantity consumed for the discount (decimal value as string)</td></tr><tr><td>basket.basketItems[].appliedDiscounts[].discount.extraArgs</td><td>Object</td><td>Additional arguments for the discount</td></tr><tr><td>basket.basketItems[].product</td><td>Object</td><td>Product information</td></tr><tr><td>basket.basketItems[].product.id</td><td>Number</td><td>Unique identifier for the product</td></tr><tr><td>basket.basketItems[].product.sku</td><td>String</td><td>Stock Keeping Unit of the product</td></tr><tr><td>basket.basketItems[].product.name</td><td>String</td><td>Name of the product</td></tr><tr><td>basket.basketItems[].product.attributes</td><td>Object</td><td>Additional attributes of the product</td></tr><tr><td>basket.basketItems[].product.attributes.categoryId</td><td>String</td><td>Category id of the product</td></tr><tr><td>basket.basketItems[].product.attributes.variantId</td><td>String</td><td>Variant id of the product</td></tr><tr><td>usedDiscounts</td><td>Array</td><td>List of used discount identifiers</td></tr><tr><td>usedDiscounts[]</td><td>String</td><td>Unique identifier for a used discount</td></tr><tr><td>order</td><td>Object</td><td>Order information (sent when notifying after order creation)</td></tr><tr><td>order.orderNumber</td><td>String</td><td>Order number</td></tr></tbody></table>

**Request Body Example**

```json
{
    "basket": {
        "id": 32,
        "version": 1758199055052632,
        "voucherCode": null,
        "basketItems": [
            {
                "id": 49,
                "unitPrice": "500.00",
                "quantity": 1,
                "unitType": "QUANTITY",
                "taxRate": "20.00",
                "totalAmount": "500.00",
                "discountAmount": "0.00",
                "globallyConsumedQuantity": "0.0",
                "currencyType": "TRY",
                "appliedDiscounts": [
                    {
                        "discount": {
                            "type": "basket",
                            "description": "Internal Offer",
                            "discountedBasketItems": [
                                {
                                    "pk": 49,
                                    "quantity": "1"
                                },
                                {
                                    "pk": 47,
                                    "quantity": "1"
                                }
                            ],
                            "conditionConsumedBasketItems": [
                                {
                                    "pk": 47,
                                    "quantity": "1"
                                }
                            ],
                            "extraArgs": {
                                "discount": "12.32"
                            }
                        }
                    }
                ],
                "product": {
                    "id": 100009,
                    "sku": "SKU8",
                    "name": "Test Product 8",
                    "attributes": {
                        "categoryId": "electronics",
                        "variantId": "red-xl"
                    }
                }
            }
        ]
    },
    "usedDiscounts": [
        "v2-spring-discount-2025",
        "v2-loyalty-reward-2025"
    ],
    "order": {
        "orderNumber": "ORD-12345"
    }
}
```

**Request Body (typescript interface)**

```ts
interface BasketOffersUsedRequest {
  basket: Basket; 
  usedDiscounts: string[];
  order: UsedOffersOrder;
}

/** Order information sent when notifying after order creation (e.g. use_loyalty_card_points) */
interface UsedOffersOrder {
  orderNumber: string;
}

interface Basket {
  id: number;
  version: number;
  voucherCode?: string | null;
  basketItems: BasketItem[];
}

interface BasketItem {
  id: number;
  unitPrice: string;
  quantity: number;
  unitType: string;
  taxRate: string;
  totalAmount: string;
  discountAmount: string;
  globallyConsumedQuantity: string;
  currencyType: string;
  appliedDiscounts: AppliedDiscount[];
  product: Product;
}

interface AppliedDiscount {
  discount: Discount;
}

interface Discount {
  type: 'LOYALTY_POINT' | 'SAMPLE_PRODUCT' | 'DEFERRED' | 'POINT' | 'SHIPPING' | 'BASKET';
  description: string;
  discountedBasketItems: DiscountedBasketItem[];
  conditionConsumedBasketItems: ConditionConsumedBasketItem[];
}

interface DiscountedBasketItem {
  pk: number;
  quantity: string;
}

interface ConditionConsumedBasketItem {
  pk: number;
  quantity: string;
}

interface Product {
  id: number;
  sku: string;
  name: string;
  attributes: Record<string, any>;
}

```

**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)**

```json
{
    "errors": [
       {
           "code": "",
           "field": "",
           "message": ""
       }
   ]
}
```

* **Response Body (raw 4xx/5xx typescript interface)**

```ts
interface ErrorResponse {
  errors: ErrorItem[];
}

interface ErrorItem {
  code: string;
  field: string;
  message: string;
}
```

## <mark style="color:red;">Changelog</mark>

### Version 2.0.0 - September 18, 2025

#### Changed

* **Request/Response Structure**: Removed inline comments from JSON examples and moved field descriptions to structured tables
* **Data Types**: Updated field types to reflect actual implementation:
  * `unitPrice`, `totalAmount`, `discountAmount`, `taxRate` changed from Number to String
  * `discountedBasketItems[].quantity` in request changed from Number to String (decimal values serialized as strings)
  * `conditionConsumedBasketItems[].quantity` in request changed to String format (decimal values serialized as strings)
  * `extraArgs.discount` and `loyaltyData.amount` changed from Number to String (decimal values serialized as strings)
  * `globallyConsumedQuantity` changed from Number to String (decimal values serialized as strings)
* **Field Removal**: Removed `consumedQuantity` field from request bodies as this value is reset when each offer is applied
* **Field Descriptions**: Enhanced descriptions for `discountedBasketItems` and `conditionConsumedBasketItems` for better clarity
* **Product Attributes**: Changed from Array to Object structure
* **User Fields**: Updated nullable fields to properly reflect optional nature
* **Response Format**: Updated examples to match actual API responses

#### Added

* **Field Documentation**: Comprehensive tables describing all request and response fields
* **Real Examples**: Updated request and response examples with actual data from implementation
* **Type Consistency**: Improved type definitions to match actual API behavior

#### Improved

* **Documentation Structure**: Better organization with separate tables for field descriptions
* **Examples**: More realistic and comprehensive JSON examples
* **Type Safety**: Enhanced TypeScript interfaces to match actual implementation


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://apidocs.akinon.com/flows/basket-offer-flows.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
