User guide

Pricing, markup and margin

Looking for what it does rather than how to use it? Read the Pricing and margin overview .

How a cost becomes a sell price: the markup you earn, the discounts you give, and the margin left over.


What it is

Pricing takes what you pay — a distributor’s cost, a platform service’s cost price, a vendor invoice line — and turns it into what a client pays. It does that with four independent controls: a markup profile that sets your default selling price, discount rules that take money off list, bundles that fix a price for a group of items, and margin thresholds that tell you when the result is too thin.

It does not send the quote or raise the invoice. It decides the numbers those documents carry.


Concepts

ConceptWhat it is
Pricing profileYour account-wide markup policy for the storefront: a base multiplier on cost, per-category and per-brand overrides, and rounding.
Base multiplierA multiplier applied to cost. 1.25 sells a $100 cost item at $125. Null means no markup — the item sells at cost.
Category / brand ruleA markup fraction for one catalogue category or brand (0.20 = +20%), plus an optional minimum-margin floor.
Rounding ruleHow the computed price is tidied: NONE, NEAREST_CENT, NEAREST_DOLLAR, UP_TO_99 ($9.99), UP_TO_95 ($9.95).
Currency bufferAn extra hedge added to cost on a cross-currency sale, e.g. 0.03 for 3%. Opt-in; can only raise a price.
Customer markup configMarkup applied when re-billing a vendor cost to a client. Scoped by contract, account, organization or expense category.
Discount ruleA reduction off list price: volume tiers, contract-term tiers, promotions, VIP pricing, or a flat discount.
Pricing bundleA fixed price for two or more products/services, which must be no higher than buying them separately.
Margin(sell − cost) ÷ sell. A fraction of the selling price.
Markup(sell − cost) ÷ cost. A fraction of the cost. Not the same number as margin — a 25% markup is a 20% margin.
Margin thresholdsTwo fractions per account — a warning level and a critical level — that classify how thin a price is.

The four controls, in the order they apply

distributor / platform cost

        ├─ pricing profile ──►  currency buffer → base multiplier
        │                       → category markup → brand markup
        │                       → vendor markup → minimum-margin floor
        │                       → rounding
        │                                        = LIST PRICE

        ├─ discount rules ───►  volume / contract-term / promotional
        │                       / VIP / general, stacked by priority

        ├─ bundle ───────────►  fixed price, substituted for the lines
        │                       the bundle covers (other lines keep theirs)

        └─ margin check ─────►  OK / WARNING / CRITICAL / BLOCKED

Markup makes the price. Discounts and bundles reduce it. The margin check reports on the result — it never silently changes it.


Roles and permissions

platform administrator > MSP administrator > MSP technician > organization administrator > power user > CUSTOMER`

Every pricing surface listed here is floored at MSP technician, which admits platform administrator, MSP administrator and MSP technician, and excludes organization administrator, power user and CUSTOMER. That is deliberate: these screens expose your cost prices, and a cost price is not client-facing.

Actionplatform administratorMSP administratorMSP technicianorganization administratorpower userCUSTOMER
View / edit the storefront pricing profile
Create / edit / delete discount rules
Create / edit / delete bundles
Set margin thresholds
View margin analytics
Create / edit customer markup rules
Run the price & margin calculator
Manage another account’s pricing profile
Manage platform plan prices (ServiceTier)

Tenant scope. Pricing configuration is your own account’s settings and is never shared with, or inherited from, a client you service. Naming another account in a request body or query string is a 403, not a lookup — including on the read-only calculators.


Walkthroughs

Set your storefront markup

MSP portal → Store → Pricing

  1. Pick a profile: Cost Plus (add a percentage to cost), Target Margin (work back from a margin you want to keep), or Custom (per-category and per-brand rules).
  2. Drag the slider or type the percentage. The preview panel prices a worked example — $100.00 cost, $149.99 MSRP — through the same steps the engine uses.
  3. Choose a rounding rule. UP_TO_99 turns $127.34 into $127.99.
  4. Add category rules for anything that needs a different number, and brand rules for anything that needs a different number again. A category rule can also carry a minimum margin, which is a floor: if markup alone would undershoot it, the price is raised to cost ÷ (1 − minimumMargin).
  5. Save. Every product list, product detail and checkout re-prices immediately.

If the page shows “Your catalogue is currently priced at cost”, no base markup is saved and every product is selling for exactly what you pay. Set a markup and save.

Create a volume discount

MSP portal → Settings → Pricing → Add Rule

  1. Name the rule and choose Volume.
  2. Add tiers — for example 10+ units at 5%, 50+ at 10%, 100+ at 15%. The engine picks the highest tier the quantity qualifies for; tiers do not stack with each other.
  3. Choose the scope: all products, or specific products and categories.
  4. Choose the customers: all, or specific client organizations.
  5. Set a priority. Higher priorities are evaluated first, and every qualifying rule’s discount is summed.
  6. Optionally set an end date and a usage cap. Save.

Build a bundle

MSP portal → Settings → Pricing → Bundles → New bundle

  1. Search the catalogue and add at least two items with their quantities.
  2. Type the bundle price. The server prices the same items individually and returns the savings; a bundle priced above the individual total is refused with both figures quoted.
  3. Set the effective window. Save.

A bundle substitutes its price for the lines it covers. Anything else in the basket keeps its own price and is added on.

Set margin thresholds and read the analytics

MSP portal → Settings → Pricing → Margin thresholds

  1. Set a warning threshold and a critical threshold as percentages. Warning must be greater than or equal to critical. Defaults are 10% and 5%.
  2. Choose whether to alert on quotes, on invoices, or both, and optionally an email address to copy.
  3. Save. Creating the record is the opt-in — an account with no record gets no alerts at all.

The analytics panel scores the last 30 days of quoted work: how many lines are healthy, warning or critical, the blended margin, and how many lines have no cost basis. A line has no cost basis when it has no product link or the product has no tracked cost — labour and ad-hoc services, typically. Those lines are excluded from both sides of the ratio and counted separately, because reporting them as 100%-margin work would be false.

When there is no cost-bearing work in the period, the health score reads ”—”, not 0% and not 100%.

Check a price before you quote it

MSP portal → Settings → Pricing → Calculator

  1. Add products and account services to the basket and set quantities.
  2. Optionally choose a bundle and a contract length in months (contract length is what makes CONTRACT_TERM rules fire).
  3. Press Calculate.

You get the list subtotal, the discount taken, the sell price, the cost, the margin, and a per-line table naming every rule that fired and what it took off. Anything that would sell below cost is flagged.

Mark a vendor cost up to a client

MSP portal → Purchasing → Customer markup

  1. Create a rule and choose its scope: Global default, Product category, Specific customer, or Contract.
  2. Choose the markup type and value. PERCENTAGE and COST_PLUS are the same calculation — cost × value — so 0.15 is +15% either way. FIXED adds a flat dollar amount.
  3. Optionally set minimum and maximum markup amounts, which clamp the result.
  4. Set a priority and an effective window. Save.

The calculator at the top of that page prices a cost through the live ladder and names which rung answered (CONTRACT, ACCOUNT, ORGANIZATION, PRODUCT or DEFAULT).


Configuration

Pricing profile (MspPricingProfile, one per account)

SettingUnitsBoundsUnset behaviour
baseMultiplierMultiplier on cost (1.25 = +25%)0 – 10No markup — the item sells at cost.
categoryRulesFraction per category (0.20 = +20%)markup 0 – 2Category inherits the base multiplier.
brandRulesFraction per brandas aboveBrand inherits category, then base.
minimumMarginFraction of sell (0.30 = 30%)0 – 1No floor.
currencyBufferFraction added to cost0 – 0.5No hedge. Negative and zero are ignored.

Discount rule (PricingRule)

SettingNotes
typeVOLUME, CONTRACT_TERM, PROMOTIONAL, CUSTOMER_VIP, GENERAL.
discountTypePERCENTAGE (fraction), FIXED_AMOUNT (cents per unit), FIXED_PRICE (cents, replaces price).
volumeTiersRequired for VOLUME. { minQty, discountPercent }, discount as a fraction.
termTiersRequired for CONTRACT_TERM. { minMonths, discountPercent }.
effectiveUntilRequired for PROMOTIONAL.
priorityHigher first. Qualifying discounts are summed, then the line is floored at zero.
applyToAll / idsScope by product, service or category. An empty scope with applyToAll off matches nothing.
maxUsageCountStops the rule applying once usageCount reaches it. See §9 for how the counter advances.

Margin thresholds (MarginAlertConfig, one per account)

SettingDefaultNotes
warningThreshold0.10Fraction. Must be ≥ criticalThreshold.
criticalThreshold0.05Fraction.
alertOnQuotetrueEvaluate on quote creation.
alertOnInvoicetrueEvaluate on invoice creation.
notifyEmailnullExtra recipient alongside the account’s staff.

Only accounts flagged as MSP/IT partners may hold margin thresholds; the API answers 400 for any other account.


Plan tiers

Pricing, markup, margin thresholds, bundles, discount rules and the calculator carry no plan gate. None of the routers in this feature area invoke a plan-gate middleware, so every tier that can reach the MSP portal can use all of it.

What is restricted is the role floor in §3, and the MSP/IT-partner flag on the account for discount rules, bundles and margin thresholds.


Troubleshooting

What you seeWhat it means
Cannot write to another accountThe request body or query named an account that is not yours. Omit it — the server resolves your account from your session.
Only MSP/IT partner accounts can create pricing rulesThe account is not flagged as an MSP/IT partner. Discount rules, bundles and margin thresholds are MSP-only.
Margin config is only available for MSP/IT partner accountsSame cause, on the margin threshold routes.
Bundle price exceeds individual items totalThe bundle costs more than buying the parts. The response quotes both figures.
Volume rules require volumeTiers / Contract term rules require termTiersA tiered rule was saved with no tiers.
Promotional rules require an end date (effectiveUntil)A promotion with no expiry. Set one.
Warning threshold must be greater than or equal to critical thresholdThe two margin thresholds are the wrong way round.
Pricing rule has reached its usage limitusageCount has reached maxUsageCount. Raise the cap or clear the counter.
costAmount is required and must be positiveThe markup calculator was called with a zero or missing cost.
At least one price must be set…A tier per-currency price was submitted with every field null. Use DELETE to remove a currency instead.
Organization is not in this accountA markup rule was scoped to an organization belonging to another tenant.
“Your catalogue is currently priced at cost” bannerNo base multiplier is saved, so the engine returns cost unchanged. Set a markup.
Margin health reads ”—”No cost-bearing quoted work in the last 30 days. Not the same as 0%.
A discount rule exists but never appliesCheck the effective window, the usage cap, and that the scope is non-empty — a rule with applyToAll off and no ids matches nothing.

Limits and known behaviour

  • But the storefront checkout engine deliberately does not enforce usage caps and does not advance the counter, so a cap only bites where the counter is advanced explicitly. Treat it as a manual allowance, not an automatic one.
  • Discount rules do not reach quotes or invoices. Quote and invoice creation apply no PricingRule and no PricingBundle. Discounts reach the customer through the storefront and the cart; on a quote you enter the price yourself. Use the calculator (§4.5) to work out what to enter.
  • blocked is a warning, not a block. The engine reports blocked: true when a line would sell below cost. It does not refuse to return the price and nothing downstream refuses the sale.
  • There is no MSRP pricing mode. The engine prices from cost. CatalogProduct carries an MSRP for display, but no pricing path reads it, so a “sell at MSRP” profile cannot be expressed and is not offered.
  • COST_PLUS is an alias of PERCENTAGE. Both compute cost × value.
  • Brand rules price nothing in the platform-admin editor. brandRules are read by the storefront engine and are editable from Store → Pricing; the platform-admin profile editor does not expose them.
  • It is opt-in and can only raise a price.
  • profileType does not price anything. It is stored, displayed and reported on, but the storefront engine reads the multiplier and the rules, not the label.
  • Margin alerts fire on document creation only. Editing a quote or invoice does not re-evaluate it. A duplicated or revised document is a new document and is evaluated on its own merits.
  • Platform tier yearlyPriceCents is a monthly-equivalent rate billed annually, not an annual total.

Questions this guide did not answer?

Ask us. You will get a reply from someone who uses the product every day.

Book a demo Contact us

A 30-minute walkthrough against your own workflow. No slides.