Price lists per customer and currency
A price list gives particular customers their own prices for a company's products: each list is of one company (entity) and in one currency, and holds prices of its products in volume tiers (a lower price from a quantity on), each from a day. A customer takes at most one list per currency (a Swiss reseller may have a CHF list and a EUR list). A new invoice, credit note, quote or sales order line of a product proposes the customer's price for the line's quantity when there is one, and the list price otherwise; a line that gives no price takes it, and a price the line gives wins (What the system fills in). Nothing here posts. The design is ADR-0070; the controls are in the control matrix (section "Price lists", PL1 to PL5).
Everything is a REST operation first (/v1, tag "price lists" in the
generated reference); the MCP tool list_price_lists reads the same
operations. Keeping lists is drafting (scope draft), as keeping products is.
Lists
POST /v1/price-lists {entity, code?, name, currency?, prices?}
GET /v1/price-lists ?entity&active&limit
GET /v1/price-lists/{price_list_id}
PATCH /v1/price-lists/{price_list_id} name, active
The code is unique in the entity; left out, it is made from the name (Wholesale CHF is
WHOLESALE-CHF, WHOLESALE-CHF-2 when that is taken). The entity, the code and the currency never change. A list without
a currency is in the company's own. A list is never
deleted: active: false stops lines from proposing its prices and it is given to no new customer; the
customers that take it keep it, unused, until it is active again or they are given another list. Every
change is audited (price_list.create, price_list.update with the previous values). A list answers
with every price (by product, tier and the newest first) and the customers that take it.
Prices and tiers
POST /v1/price-lists/{price_list_id}/prices {product, unit_price, min_quantity?, price_period?, valid_from?}
A price names a product of the list's company (code or id), the net price of one unit, the smallest
quantity it holds for (min_quantity, default 1) and its first day (valid_from, default today where the
company is). A recurring product's price is per month or year, a one-off product's per unit, as for
list prices. A price is never changed: a new price from a later day replaces the tier's price from
that day on (409 price_list_price_exists for a second price of the product and tier from the same day).
The price in force for a quantity on a day is the lowest of the tiers the quantity reaches, each at its latest price from on or before the day: a larger quantity never costs more per unit, and a line of less than one unit (half a roll) takes the price of the first tier. With the demo's wholesale list (scanner CHF 229.00 from 1 piece, CHF 209.00 from 10 pieces, both from 1 January 2026), 9 scanners cost 229.00 each and 10 cost 209.00 each.
A customer's lists
GET /v1/entities/{entity}/customers/{party}/price-lists
PUT /v1/entities/{entity}/customers/{party}/price-lists/{currency} {price_list}
DELETE /v1/entities/{entity}/customers/{party}/price-lists/{currency}
PUT gives the customer the list (code or id, an active list of its company in that currency) in place
of the one it had in the currency; giving it the list it has changes nothing. DELETE takes the list
away; its lines propose the list price again. Both are safe to repeat and audited on the customer
(party.price_list, with the previous list). 422 price_list_currency for a list in another currency,
409 price_list_inactive for an inactive one, 409 price_list_assigned_meanwhile when someone else gave
the customer its first list in the currency at the same moment, 404 for a vendor or an unknown customer.
What a line proposes
GET /v1/products/{product_id}/price ?currency&on&party&quantity
With party (a customer of the product's company) the answer carries, beside the list price and SSP in
force, customer_price: the customer's price for the quantity (default 1) from the active list it
takes in the currency, with the list (price_list, price_list_name) and the tier (min_quantity) it
came from; null when it takes none, the list is inactive or has no price of the product for the
quantity on the day. The screens' line proposes it and says so in plain words ("Customer price
209.00 CHF from the price list Wholesale CHF for 10 or more, valid from 01.01.2026. List price:
249.00 CHF."). A price left as proposed follows a new quantity, customer, currency or date; a typed price
stays. A credit note line that credits an invoice line keeps the price that line was invoiced at:
nothing is proposed for it, so crediting 2 of 12 scanners invoiced at 209.00 credits 209.00 each.
Screens
Sales > Price lists lists the lists with their currency, number of prices and customers; New price list creates one; a list's card shows its prices by product and tier (in force, replaced or upcoming), its customers, Add price and Deactivate. The customer card has a Price lists section: the list per currency, Change, Remove and Give a price list.
Not built
Recurring invoice templates and subscriptions do not read price lists (a subscription's prices are its approved terms). Lists across currencies or companies, percentage discounts per list or product group, and the list's name on the PDF are not built.