Deals & Discounts
ON THIS PAGE
Suppliers can give customers lower prices in three ways: discounted prices, Deals, and Supplier Assist discounts. This page explains how each one is set up, how it changes the order total, and how it appears in the order_placed webhook.
Discount types
| Type | What it is | Where you set it | Where it appears in order_placed |
|---|---|---|---|
| Discounted price | A lower unit price on one product, optionally between two dates | Product sync | Already included in items[].total_price |
| Deal | A promotion that applies when the cart meets your conditions. It can be a percentage off, a fixed amount off, a bundle, Buy X Get Y, or free shipping | Deals in Control | discounts, with source: "deal" |
| Supplier Assist | A one-off percentage or fixed amount taken off a quote | Supplier Assist quote | discounts, with source: "supplier_assist" |
Note: A price tier is not a discount. It sets a customer's normal catalogue price. Tier pricing is already included in items[].total_price and never appears in discounts.
How the order total is calculated
Shop order
- Unit price. The customer pays the lowest of these prices:
- the product's list price
- their price tier, if they have one
- the discounted price, if today falls within its dates
- Line totals. Unit price x quantity. Together these make
subtotal_price. - Deals. Deals run in priority order. Each Deal is calculated on the amount left after earlier Deals.
- Shipping. It is added when the order has a delivery charge. A free-shipping Deal sets it to zero.
- Tax. Tax is charged on
subtotal+shipping−discountsonly in Australia, the United Kingdom, and Germany. It is not charged in other countries, including the United States and Canada.
Supplier Assist quote
- Line totals. The prices on the quote are used as approved by the account manager.
- Quote discount. If the account manager added a discount, it is taken off the whole quote.
- Shipping, if provided, then tax. Tax is charged on
subtotal+shipping−quote discount.
Deals never run on a Supplier Assist order, so they cannot change the price your account manager approved.
Order totals in order_placed
| Field | Description |
|---|---|
items[].total_price | Line total after catalogue, tier, or quote pricing, and before Deals and Supplier Assist |
subtotal_price | Sum of all line totals |
discounts.total_discount_amount | Amount taken off by Deals and Supplier Assist |
total_tax | Tax on subtotal + shipping − discounts |
total_price | subtotal + shipping − discounts + tax |
Tax is calculated only in these countries:
| Country | Tax |
|---|---|
| Australia | GST, 10% |
| United Kingdom | VAT, 20% |
| Germany | VAT, 19% |
For every other country, including the United States and Canada, total_tax is "0.00". Confirm tax with the customer when you process the order.
Example: a UK shop order
The cart has 10 × Panel A at £200 and 1 × Inverter at £1,000. Two Deals apply:
priority10: 10% off each modulepriority20: £100 off the cart
Shipping is £50.
| Step | Amount |
|---|---|
| Subtotal (£2,000 + £1,000) | £3,000.00 |
| Deal 1: 10% off panels (10% of £2,000) | −£200.00 |
| Deal 2: £100 off the cart | −£100.00 |
| Shipping | £50.00 |
| VAT, 20% of £2,750 | £550.00 |
| Total | £3,300.00 |
{
"order_id": 1234,
"total_items": 11,
"subtotal_price": "3000.00",
"total_tax": "550.00",
"total_price": "3300.00",
"items": [
{
"quantity": 10,
"product_code": "PANEL-A",
"title": "Panel A",
"total_price": "2000.00",
"distributor_product_code": "DIST-PANEL-A"
},
{
"quantity": 1,
"product_code": "INV-1",
"title": "Inverter",
"total_price": "1000.00",
"distributor_product_code": "DIST-INV-1"
}
],
"shipping_cost": {
"label": "Standard Delivery",
"cost": 50.0
},
"discounts": {
"currency": "GBP",
"total_discount_amount": "300.00",
"discount_applications": [
{
"id": "deal:42",
"source": "deal",
"type": "percentage",
"title": "10% off panels",
"description": "10% off all modules",
"target": "line_item",
"value": {
"kind": "percentage",
"amount": "10.00"
},
"priority": 10
},
{
"id": "deal:43",
"source": "deal",
"type": "fixed_amount",
"title": "£100 off",
"description": "",
"target": "order",
"value": {
"kind": "fixed_amount",
"amount": "100.00"
},
"priority": 20
}
],
"discount_allocations": [
{
"discount_application_id": "deal:42",
"target": "line_item",
"sku": "DIST-PANEL-A",
"amount": "200.00"
},
{
"discount_application_id": "deal:43",
"target": "order",
"sku": null,
"amount": "100.00"
}
]
}
}
The line totals show prices before Deals. The £300 in Deals is only in discounts.
Discounted prices
A discounted price replaces a product's list price. You send it with the product in product sync.
| Field | Required | Description |
|---|---|---|
discounts.type | Yes | percentage_off or discount_price |
discounts.value | Yes | For percentage_off, the percent off the list price. For example, 10 is 10% off, and the maximum is 100. For discount_price, the new unit price, from zero up to the list price. |
discounts.starts_at | No | First day the discount applies, DD/MM/YYYY |
discounts.ends_at | No | Last day the discount applies, DD/MM/YYYY |
Both dates are included in the discount period. Outside the dates, the list price is used. If you leave out both dates, the discount always applies, until overridden in a new product sync.
Example: set a discounted price in product sync
Panel A lists at £250. This gives 20% off, so £200, for October 2026.
{
"products": [
{
"product_code": "PANEL-A",
"title": "Panel A",
"price": 250.0,
"currency_code": "GBP",
"stock_level": 40,
"discounts": {
"type": "percentage_off",
"value": 20,
"starts_at": "01/10/2026",
"ends_at": "31/10/2026"
}
}
]
}
To set a sale price of £200 instead of a percentage, send:
{
"discounts": {
"type": "discount_price",
"value": 200
}
}
In a CSV upload, use the columns discounts_type, discounts_value, discounts_starts_at, and discounts_ends_at.
How it appears in the order
Two units at the £200 discounted price:
{
"items": [
{
"quantity": 2,
"product_code": "PANEL-A",
"title": "Panel A",
"total_price": "400.00",
"distributor_product_code": "DIST-PANEL-A"
}
],
"discounts": null
}
The £100 saving is not shown separately. With no Deal or Supplier Assist discount, discounts is null.
Discounted price and price tier together
If a customer has both, they pay whichever is lower.
| List price | Customer's tier price | Discounted price | Customer pays |
|---|---|---|---|
| £250 | £210 | £200 | £200 (discounted price) |
| £250 | £190 | £200 | £190 (tier price) |
Deals
A Deal applies a discount when the cart meets your conditions. Deals apply only to your own products in the cart. You create them in Control -> Supplier -> Deals.
A Deal applies only when all of these are true:
- Active is turned on.
- Today is on or after the start date.
- The end date is empty, or today is on or before it.
Deal dates are calendar dates (YYYY-MM-DD). A Deal that is inactive or outside its dates is skipped, and later Deals still run.
Conditions
Every condition on a Deal must be met.
| Condition | What it checks | Options |
|---|---|---|
| Cart subtotal | The value of your products in the cart | At least, at most, equal to, or between two values (both included) |
| Cart quantity | Total units of your products in the cart | At least, at most, equal to, or between |
| Item quantity | Quantity on at least one line | At least, at most, equal to, or between |
| Product | A specific product is in the cart | That product, any of a list, or all of a list |
| Products (bundle) | A set of products is in the cart | Any of the set, or all of the set |
| Component category | A line's category is module, inverter, battery, or other | That category, or any of a list |
- Cart subtotal is checked after earlier Deals have been taken off.
- Product and category conditions also decide which lines the discount applies to.
- With no product or category condition, the Deal covers all your products in the cart.
Actions
| Discount | What the customer gets | type |
|---|---|---|
| Percentage off | A percentage off the chosen lines, the cart, or the bundle | percentage |
| Fixed amount off | A set amount off the chosen lines, the cart, or the bundle | fixed_amount |
| Free shipping | No shipping charge for your products | free_shipping |
| Buy X Get Y | Free units once the customer buys enough | bxgy |
Apply to
Percentage and fixed-amount Deals have an Apply to setting.
| Apply to | What is discounted | Allocations in the webhook |
|---|---|---|
| Each item | Every line the Deal covers | One line_item allocation per product |
| Cart total | The cart, once | One order allocation with sku: null |
| Bundle total | The bundle, once | One line_item allocation per bundle product, split by line total |
- Bundle total is only available when the Deal has a Products (bundle) condition.
- If Apply to is not set, a fixed amount applies once to the cart and a percentage applies to each item.
For fixed amounts:
- Each item: the amount is taken off every unit, and never more than the line total. £10 off each unit × 5 units = £50.
- Cart total: the amount is taken off once, and never more than the cart total.
- Bundle total: the amount is taken off the bundle once, and never more than the bundle total.
Buy X Get Y
Same product
The customer needs a complete set in the cart: the buy quantity plus the free quantity.
- For "Buy 2 get 1 free", 3 units earn 1 free unit, and 6 units earn 2.
- Units that do not complete a set are charged in full.
Different product
The free product must already be in the cart. The Deal does not add it for the customer.
- For "Buy 10 panels, get 1 optimiser free", 20 panels earn 2 free optimisers.
- The customer never gets more free units than they have in the cart.
Priority and limits
- Priority. Lower numbers run first. Each Deal is calculated on the price left after earlier Deals.
- Stop further Deals. When this Deal's conditions are met, no later Deal runs, even if this Deal takes off nothing. Free-shipping Deals do not stop later Deals.
- Maximum discount amount. This caps what a percentage, fixed amount, or Buy X Get Y Deal can take off. Leave it empty or at zero for no cap. It does not apply to free shipping.
Deal examples
Each example shows the discounts object from order_placed.
Percentage off each item
10% off Panel A (£2,000) and Panel B (£500):
{
"discounts": {
"currency": "GBP",
"total_discount_amount": "250.00",
"discount_applications": [
{
"id": "deal:42",
"source": "deal",
"type": "percentage",
"title": "10% off panels",
"description": "10% off selected panels",
"target": "line_item",
"value": {
"kind": "percentage",
"amount": "10.00"
},
"priority": 10
}
],
"discount_allocations": [
{
"discount_application_id": "deal:42",
"target": "line_item",
"sku": "DIST-PANEL-A",
"amount": "200.00"
},
{
"discount_application_id": "deal:42",
"target": "line_item",
"sku": "DIST-PANEL-B",
"amount": "50.00"
}
]
}
}
Fixed amount off the cart
£25 off the cart:
{
"discounts": {
"currency": "GBP",
"total_discount_amount": "25.00",
"discount_applications": [
{
"id": "deal:43",
"source": "deal",
"type": "fixed_amount",
"title": "£25 off",
"description": "",
"target": "order",
"value": {
"kind": "fixed_amount",
"amount": "25.00"
},
"priority": 20
}
],
"discount_allocations": [
{
"discount_application_id": "deal:43",
"target": "order",
"sku": null,
"amount": "25.00"
}
]
}
}
Bundle total
5% off a bundle of Panel A (£2,000) and Inverter (£1,000). The £150 is split by each line's share of the bundle:
{
"discounts": {
"currency": "GBP",
"total_discount_amount": "150.00",
"discount_applications": [
{
"id": "deal:44",
"source": "deal",
"type": "percentage",
"title": "Panel + inverter",
"description": "5% off the bundle",
"target": "line_item",
"value": {
"kind": "percentage",
"amount": "5.00"
},
"priority": 10
}
],
"discount_allocations": [
{
"discount_application_id": "deal:44",
"target": "line_item",
"sku": "DIST-PANEL-A",
"amount": "100.00"
},
{
"discount_application_id": "deal:44",
"target": "line_item",
"sku": "DIST-INV-1",
"amount": "50.00"
}
]
}
}
Buy X Get Y, same product
Buy 2 get 1 free, with 6 × Panel A at £200. That is 2 complete sets, so 2 units are free:
{
"discounts": {
"currency": "GBP",
"total_discount_amount": "400.00",
"discount_applications": [
{
"id": "deal:55",
"source": "deal",
"type": "bxgy",
"title": "Buy 2 get 1 free",
"description": "",
"target": "line_item",
"value": {
"kind": "bxgy"
},
"priority": 5
}
],
"discount_allocations": [
{
"discount_application_id": "deal:55",
"target": "line_item",
"sku": "DIST-PANEL-A",
"amount": "400.00"
}
]
}
}
Buy X Get Y, different product
Buy 10 panels, get 1 optimiser free. The cart has 20 panels and 2 optimisers at £50, so both optimisers are free. The allocation is on the free product:
{
"discount_allocations": [
{
"discount_application_id": "deal:56",
"target": "line_item",
"sku": "DIST-OPT-1",
"amount": "100.00"
}
]
}
Free shipping
{
"discounts": {
"currency": "GBP",
"total_discount_amount": "0.00",
"discount_applications": [
{
"id": "deal:free-shipping",
"source": "deal",
"type": "free_shipping",
"target": "shipping",
"value": {
"kind": "free_shipping"
}
}
],
"discount_allocations": [
{
"discount_application_id": "deal:free-shipping",
"target": "shipping",
"sku": null,
"amount": "0.00"
}
]
}
}
- Free shipping always uses the
iddeal:free-shipping. It has notitle,description, orpriority. - The allocation is
"0.00". The saving is the shipping fee that was not charged.
Supplier Assist
A Supplier Assist discount is added to a quote by your account manager. It always applies to the whole order, never to single products.
| Quote discount | Meaning | value.kind |
|---|---|---|
| Percentage | A percentage of the quote subtotal, before shipping | percentage |
| Fixed | A set amount off the quote | fixed_amount |
- The discount label can be up to 40 characters.
- The application
idissupa:followed by the label in lowercase with hyphens. For example, "Early Bird 10%" becomessupa:early-bird-10.
Example: percentage
10% off a £1,200 subtotal:
{
"discounts": {
"currency": "GBP",
"total_discount_amount": "120.00",
"discount_applications": [
{
"id": "supa:early-bird-10",
"source": "supplier_assist",
"type": "percentage",
"title": "Early Bird 10%",
"description": null,
"target": "order",
"value": {
"kind": "percentage",
"amount": "10.00"
},
"priority": null
}
],
"discount_allocations": [
{
"discount_application_id": "supa:early-bird-10",
"target": "order",
"sku": null,
"amount": "120.00"
}
]
}
}
value.amount is the rate (10%). The allocation amount is the money taken off (£120).
Example: fixed amount
£50 off:
{
"discounts": {
"currency": "GBP",
"total_discount_amount": "50.00",
"discount_applications": [
{
"id": "supa:goodwill",
"source": "supplier_assist",
"type": "fixed_amount",
"title": "Goodwill",
"description": null,
"target": "order",
"value": {
"kind": "fixed_amount",
"amount": "50.00"
},
"priority": null
}
],
"discount_allocations": [
{
"discount_application_id": "supa:goodwill",
"target": "order",
"sku": null,
"amount": "50.00"
}
]
}
}
discounts object reference
discounts is null when the order has no Deal and no Supplier Assist discount. When the only promotion is free shipping, it is still sent, with total_discount_amount of "0.00".
| Field | Type | Description |
|---|---|---|
currency | string | Currency code, for example GBP |
total_discount_amount | string | Total taken off by Deals and Supplier Assist. Always equals the sum of the allocations |
discount_applications | array | Each promotion that was applied |
discount_allocations | array | The amount each promotion took off, and where |
Applications say which promotion ran and how it was set up. Allocations say how much money it took off and from where. One application can have several allocations.
Discount application
| Field | Type | Description |
|---|---|---|
id | string | deal:<id>, deal:free-shipping, or supa:<label> |
source | string | deal or supplier_assist |
type | string | percentage, fixed_amount, bxgy, or free_shipping |
title | string | Deal title (up to 20 characters) or Supplier Assist label |
description | string | null | Deal description. null for Supplier Assist |
target | string | line_item, order, or shipping |
value.kind | string | Same as type |
value.amount | string | The percentage or fixed amount you set, not the money taken off. Not included for Buy X Get Y or free shipping |
priority | integer | null | Deal priority. null for Supplier Assist |
Discount allocation
| Field | Type | Description |
|---|---|---|
discount_application_id | string | The id of the matching application |
target | string | line_item, order, or shipping |
sku | string | null | Your product code (distributor_product_code) when you have one, otherwise the OpenSolar product code. null for order and shipping |
amount | string | Money taken off |
The old top-level discount_amount field is no longer sent. Use the Supplier Assist application and its allocation instead.
Quick reference
| You want to know | Look at |
|---|---|
| The price the customer paid for a product | items[].total_price |
| Whether a discounted price or price tier applied | Already included in items[].total_price |
| Which Deals applied | discount_applications where source is deal |
| How much a Deal took off | That Deal's discount_allocations |
| Whether Supplier Assist applied | An application where source is supplier_assist |
| How much Supplier Assist took off | Its allocation |
| Whether shipping was free | An allocation where target is shipping |