Incentives in order data
When an incentive rule fires, the result is written into the order's items array rather than into a separate discounts block. Two different kinds of line are produced, and an integration that treats every entry in items as a purchasable product will misread the order.
Line classes
Every order item carries a class:
| Class | What it is | Counts toward what the customer pays |
|---|---|---|
product | A real line. Either something the customer added or a product a rule added | Yes |
incentive | A record of an adjustment a rule made, attached to a product line | No, the adjustment is already reflected in the product line |
surcharge | An additional fee such as handling or a small order fee | Yes |
An incentive line always has productId: null and a parentOrderItemId pointing at the line it adjusts.
A product added by a rule keeps class: product. It is a real, orderable line. What marks it as given rather than chosen is isBonus: "Y".
What a rule produces
Take an order where the customer added one product and two rules fired. The order has five items:
id | class | parentOrderItemId | isBonus | What it is |
|---|---|---|---|---|
| 14810 | product | null | N | The product the customer added |
| 14811 | product | null | Y | A line a rule added |
| 14812 | incentive | 14811 | Y | The rule that produced line 14811 |
| 14813 | product | null | Y | A line a second rule added |
| 14814 | incentive | 14813 | Y | The rule that produced line 14813 |
One applied incentive therefore produces two entries: the line the customer gets, and the record explaining where it came from.
Reading an incentive line
{
"id": 14814,
"class": "incentive",
"productId": null,
"parentOrderItemId": 14813,
"sku": "discount_percentage",
"name": "Untitled rule",
"originalPrice": -5,
"price": -5,
"priceTotal": -5,
"isBonus": "Y"
}
| Field | Meaning on an incentive line |
|---|---|
sku | The action that fired, not a product code. Values include discount_percentage and set_price |
name | The name of the rule or subrule. Unnamed subrules appear as Untitled subrule |
price and priceTotal | The effect of the action, not a price to charge. Negative for a discount, so -5 means five off. For set_price it is the price that was set |
parentOrderItemId | The line this adjustment applies to |
productId | Always null |
The product line already reflects the adjustment. Line 14813 above carries price: 10 and priceTotal: 5, so the customer pays 5. The incentive line records that a rule took 5 off. Adding the two together double-counts it.
What integrations should do
Read class before anything else. An ERP export, invoice, picking list or analytics feed that iterates items without checking class will treat adjustment records as sellable lines.
Skip incentive lines as line items, but keep surcharge. Incentive lines are metadata and their value is already inside the product line. Surcharges are real charges the customer pays. Filtering to class == "product" alone silently drops them.
Send bonus products to the warehouse. A line with isBonus: "Y" and class: product is physical stock that has to be picked and shipped. Its incentive record must not be.
Do not match incentive lines on sku. The field holds the action name, so it collides with product SKU lookups.
Use parentOrderItemId to attribute a discount. It is the only link between an adjustment and the line it applies to.
See also
- Business rules overview for how rules are evaluated
- Rule types for the incentive actions that produce these lines
- Order history for the rest of the order item model