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. A discount on a line arrives as its own order line with a negative amount. An integration that books only product lines, or that treats every entry in items as a purchasable product, gets the order wrong.
Line classes
Every order item carries a class:
| Class | What it is | Counts toward the order total |
|---|---|---|
product | A real line. Either something the customer added or a product a rule added | Yes, at its price before any incentive |
incentive | The adjustment a rule made to one product line, as a negative amount | Yes, it lowers the total |
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 product line it adjusts. A product line has at most one incentive line.
A product added by a rule keeps class: product. It is a real, orderable line at its normal price. What marks it as given rather than chosen is isBonus: "Y", and its incentive line brings it down to what the customer pays.
What a rule produces
Take an order where a rule gives 20% off two of the three products the customer added. The order has five items:
id | class | parentOrderItemId | quantity | price | priceTotal | What it is |
|---|---|---|---|---|---|---|
| 14810 | product | null | 3 | 20 | 60 | A product the rule covers |
| 14811 | incentive | 14810 | 3 | -4 | -12 | The 20% off line 14810 |
| 14812 | product | null | 2 | 15 | 30 | A second product the rule covers |
| 14813 | incentive | 14812 | 2 | -3 | -6 | The 20% off line 14812 |
| 14814 | product | null | 1 | 4 | 4 | A product the rule does not cover |
The lines add up to 76: 94 for the products and -18 for the incentives. The order total is that amount plus shipping and payment costs.
A rule that adds a free product produces two lines:
id | class | parentOrderItemId | isBonus | quantity | price | priceTotal | What it is |
|---|---|---|---|---|---|---|---|
| 14821 | product | null | Y | 1 | 30 | 30 | The product the rule added, at its normal price |
| 14822 | incentive | 14821 | Y | 1 | -30 | -30 | The adjustment that makes it free |
Reading an incentive line
{
"id": 14811,
"class": "incentive",
"productId": null,
"parentOrderItemId": 14810,
"sku": "discount_percentage",
"name": "20% off ear protection",
"quantity": 3,
"originalPrice": -4,
"price": -4,
"priceTotal": -12,
"customerPrice": 0,
"isBonus": "N"
}
| Field | Meaning on an incentive line |
|---|---|
sku | The kind of adjustment, not a product code. See the next table |
name | The name given to the rule's action that produced it |
price | The adjustment per piece. Negative, so -4 means four off each piece |
quantity | The pieces the adjustment applies to. Usually the quantity of the product line, but a "3 for 2" rule counts only the free pieces, for example 1 on a line of 3 |
priceTotal | price times quantity: the amount the line takes off the order |
parentOrderItemId | The product line this adjustment applies to |
productId | Always null |
customerPrice | Always 0 |
sku | Produced by |
|---|---|
discount_percentage | A percentage discount on the line |
discount | A fixed amount off each piece |
free | Pieces the customer gets for free, such as the cheapest piece in a "3 for 2" or a product a rule added at price 0 |
set_price | A product a rule added at a set price. price is the set price minus the normal price, so a product that normally costs 30, added at 5, gives -25 |
The product line keeps its price before the incentive. Line 14810 above carries price: 20 and priceTotal: 60. The customer pays 48 for it: the 60 of the product line plus the -12 of its incentive line.
When two rules adjust the same product line, the order keeps the adjustment of the rule that was created last. Rules that adjust different lines each produce their own incentive line.
A discount on the order total does not produce a line. It is in total.discountType (P for a percentage, A for an amount) and total.discountValue, and it is already taken off the order total.
The product line's own discount field is not the incentive. It is originalPrice minus price plus the incentive per piece, so it also contains any difference between the product's list price and the customer's price. Read the adjustment from the incentive line.
What integrations should do
Read class before anything else. Handle each class you know and stop with an error on a class you do not know. An ERP export, invoice, picking list or analytics feed that skips lines it does not recognize can silently change what the order is worth.
Book incentive lines, do not skip them. The discount exists only on the incentive line. For the amount the customer pays for a product line, add the priceTotal of its incentive line, matched on parentOrderItemId, to the product line's priceTotal. Alternatively, book the incentive line as a discount line of its own in the receiving system. Skipping it books the order at full price.
Keep surcharges. 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 line is not.
Do not match incentive lines on sku. The field holds the kind of adjustment, 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
- Export orders for sending orders to an ERP or WMS