Skip to main content

Deals & Discounts

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​

TypeWhat it isWhere you set itWhere it appears in order_placed
Discounted priceA lower unit price on one product, optionally between two datesProduct syncAlready included in items[].total_price
DealA 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 shippingDeals in Controldiscounts, with source: "deal"
Supplier AssistA one-off percentage or fixed amount taken off a quoteSupplier Assist quotediscounts, 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​

  1. 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
  2. Line totals. Unit price x quantity. Together these make subtotal_price.
  3. Deals. Deals run in priority order. Each Deal is calculated on the amount left after earlier Deals.
  4. Shipping. It is added when the order has a delivery charge. A free-shipping Deal sets it to zero.
  5. Tax. Tax is charged on subtotal + shipping − discounts only in Australia, the United Kingdom, and Germany. It is not charged in other countries, including the United States and Canada.

Supplier Assist quote​

  1. Line totals. The prices on the quote are used as approved by the account manager.
  2. Quote discount. If the account manager added a discount, it is taken off the whole quote.
  3. 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​

FieldDescription
items[].total_priceLine total after catalogue, tier, or quote pricing, and before Deals and Supplier Assist
subtotal_priceSum of all line totals
discounts.total_discount_amountAmount taken off by Deals and Supplier Assist
total_taxTax on subtotal + shipping − discounts
total_pricesubtotal + shipping − discounts + tax

Tax is calculated only in these countries:

CountryTax
AustraliaGST, 10%
United KingdomVAT, 20%
GermanyVAT, 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:

  • priority 10: 10% off each module
  • priority 20: £100 off the cart

Shipping is £50.

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

FieldRequiredDescription
discounts.typeYespercentage_off or discount_price
discounts.valueYesFor 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_atNoFirst day the discount applies, DD/MM/YYYY
discounts.ends_atNoLast 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 priceCustomer's tier priceDiscounted priceCustomer 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.

ConditionWhat it checksOptions
Cart subtotalThe value of your products in the cartAt least, at most, equal to, or between two values (both included)
Cart quantityTotal units of your products in the cartAt least, at most, equal to, or between
Item quantityQuantity on at least one lineAt least, at most, equal to, or between
ProductA specific product is in the cartThat product, any of a list, or all of a list
Products (bundle)A set of products is in the cartAny of the set, or all of the set
Component categoryA line's category is module, inverter, battery, or otherThat 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​

DiscountWhat the customer getstype
Percentage offA percentage off the chosen lines, the cart, or the bundlepercentage
Fixed amount offA set amount off the chosen lines, the cart, or the bundlefixed_amount
Free shippingNo shipping charge for your productsfree_shipping
Buy X Get YFree units once the customer buys enoughbxgy

Apply to​

Percentage and fixed-amount Deals have an Apply to setting.

Apply toWhat is discountedAllocations in the webhook
Each itemEvery line the Deal coversOne line_item allocation per product
Cart totalThe cart, onceOne order allocation with sku: null
Bundle totalThe bundle, onceOne 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 id deal:free-shipping. It has no title, description, or priority.
  • 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 discountMeaningvalue.kind
PercentageA percentage of the quote subtotal, before shippingpercentage
FixedA set amount off the quotefixed_amount
  • The discount label can be up to 40 characters.
  • The application id is supa: followed by the label in lowercase with hyphens. For example, "Early Bird 10%" becomes supa: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".

FieldTypeDescription
currencystringCurrency code, for example GBP
total_discount_amountstringTotal taken off by Deals and Supplier Assist. Always equals the sum of the allocations
discount_applicationsarrayEach promotion that was applied
discount_allocationsarrayThe 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​

FieldTypeDescription
idstringdeal:<id>, deal:free-shipping, or supa:<label>
sourcestringdeal or supplier_assist
typestringpercentage, fixed_amount, bxgy, or free_shipping
titlestringDeal title (up to 20 characters) or Supplier Assist label
descriptionstring | nullDeal description. null for Supplier Assist
targetstringline_item, order, or shipping
value.kindstringSame as type
value.amountstringThe percentage or fixed amount you set, not the money taken off. Not included for Buy X Get Y or free shipping
priorityinteger | nullDeal priority. null for Supplier Assist

Discount allocation​

FieldTypeDescription
discount_application_idstringThe id of the matching application
targetstringline_item, order, or shipping
skustring | nullYour product code (distributor_product_code) when you have one, otherwise the OpenSolar product code. null for order and shipping
amountstringMoney 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 knowLook at
The price the customer paid for a productitems[].total_price
Whether a discounted price or price tier appliedAlready included in items[].total_price
Which Deals applieddiscount_applications where source is deal
How much a Deal took offThat Deal's discount_allocations
Whether Supplier Assist appliedAn application where source is supplier_assist
How much Supplier Assist took offIts allocation
Whether shipping was freeAn allocation where target is shipping