Pricing & listing rules
floorPrice, buyNowPrice, startBidPrice, and the per-vehicle rules that answer offers automatically.
TL;DRAI summary
This chapter explains how Cypress uses three key prices—buy now, floor, and start bid—to automatically handle buyer offers for your vehicles. You set the rules for when offers are accepted, declined, or sent to you for review, ensuring no vehicle sells below your minimum price without your approval.
Three prices travel with a listing, and the first two arm the vehicle's listing rules: the per-vehicle lines that answer buyer offers without waiting for a person.
The three prices
| Field | Meaning |
|---|---|
buyNowPrice | The listing price buyers see. Required before go-live. Offers at or above it auto-accept. |
floorPrice | Your minimum. Offers below it are declined automatically. |
startBidPrice | Kept on the vehicle and returned as you pushed it. Since 1.5.0 it sets no band. |
How an offer is answered
One rule, whoever sets the price
A listing created or repriced through the API stamps the vehicle's offer
rules by the same rule as the app, Cedar and an approved price change:
auto-decline below floorPrice, auto-accept at or above
buyNowPrice, and your personal review between the two. You see them on
the vehicle's Offer Rules tab the moment the listing goes live. A vehicle
priced by a pricing rule keeps its rule: when its floor moves, the rule's
lines are worked again from the new floor. Other lines (accepting at the
floor, say) are a pricing rule's or an automation's to set: ask your
Cypress manager, or use the Apply pricing rule automation action.
Changed in 1.5.0: a price push used to accept at the floor and decline
below startBidPrice.
The floor is a promise
A vehicle is never sold below your floor price without your consent. No rule, automation, app or agent accepts below it; a person at your organization can, by hand, and the audit trail records exactly who did.
The events tell you which path an offer took: OFFERS.CREATED for every
offer, immediately followed by OFFERS.ACCEPTED or OFFERS.DECLINED with
"autoProcessed": true when a rule decided; an offer in your review band
fires its outcome event only when you decide. OFFERS.ACCEPTED is also
sent, without autoProcessed, when the seller accepts by hand, when the
buyer accepts the seller's counter, and when an approved price change accepts
an offer that now qualifies (see
Webhooks).
A worked example
Your F-150 lists at $22,500 with floorPrice: 18000. Three offers
arrive the first week:
| Offer | What happens | Your events |
|---|---|---|
| $16,800 | Below your floor: declined instantly, the buyer told immediately | OFFERS.CREATED → OFFERS.DECLINED (autoProcessed: true) |
| $20,500 | Between your floor and your listing price: routed to you; accept, counter or decline | OFFERS.CREATED, then the outcome when you decide |
| $22,500 | At your listing price: it auto-accepts and the closing opens | OFFERS.CREATED → OFFERS.ACCEPTED → CLOSING.STARTED |
The band boundaries come straight from your listing payload: pushing good prices IS configuring the negotiation.
Updating prices
PATCH /api/v1/listings/{id} (or a compat offering POST) applies
immediately — to the vehicle and the live marketplace listing. Bulk
repricing: PATCH /api/v1/listings/bulk with vins or listingIds, up to
500 per call.
Since 1.5.0 a price change goes through the same rules as one made in the app, on every one of these routes:
- No price moves under a live offer or a sale. While the vehicle is Under
Offer, Offer Accepted, in Due Diligence, Ready to Deliver or Sold, its price
is the one a deal was agreed against: a change answers
409 CONFLICT. - A buy-now never sits below the floor, as it is or as the same request
sets it:
403 BELOW_FLOOR. A buy-now on a vehicle with no floor answers422 INVALID("Set a floor price first"), since the price is measured against it. - The floor is the seller's. An agent never sets it (
403 PEOPLE_ONLY); an API key acts as your organization and may. An agent may set the buy-now (listing) price, here and through the app's actions (set_listing_prices,edit_vehicle), within these same rules: never below the floor, never while a live offer or a sale is open.
Nothing is written when a change is refused. On the bulk route each item is
refused on its own, with its code, and the rest of the batch goes ahead. A
single PATCH also takes ?dryRun=true and an Idempotency-Key. Before
1.5.0 these changes were written.
Every price change re-arms the lines to the prices as they now stand, and a vehicle priced by a pricing rule has its rule worked again from the new floor.
Floors for many vehicles at once
POST /api/v1/vehicles/floor-prices (set_floor_prices) sets the floor of
up to 500 vehicles not yet on the market, in one of four modes: absolute
(an amount), multiplier or fixed-delta (from each vehicle's latest retail
valuation) and, since 1.9.0, wholesale-percent: the latest wholesale
valuation plus value percent, so { "mode": "wholesale-percent", "value": 2 }
sets each floor 2% over wholesale: Cypress's own floor default (since 1.10.0
the one every suggestion uses: the appraisal, the pricing insight and the
vehicle form).
A floor is a promise, so it is only worked out from a valuation that is
current: one older than the refresh window (30 days, the window in which
Cypress does not pay for a new valuation) is skipped with
code: "VALUATION_STALE" and its date, unless you send allowStale: true.
Ask for a new valuation with revalue_vehicle first. A vehicle with no
valuation is skipped with code: "NO_VALUATION". The answer lists floors
(each vehicle's new floor, with the wholesale and its date) and skipped;
?dryRun=true works out every floor and writes nothing. Setting a floor is a
person's act: an agent's token is refused 403 PEOPLE_ONLY.
Beyond per-vehicle rules
Cypress also runs org-level pricing rules (launch pricing computed from valuations) and an automation engine that can price and launch drafts for you; your API pushes then need nothing but the vehicle data.
Your organization's own rules are yours to manage, in Settings › Pricing
rules or through the API: GET /api/v1/pricing-rules lists them with
Cypress's global ones, POST /api/v1/pricing-rules creates one, and
PATCH /api/v1/pricing-rules/{id} changes one of yours (since 1.9.0):
switch it off with isActive: false, choose applyBehavior (AUTO applies
the outcome at once, NOTIFY_CM suggests it to Cypress), or change its
conditions and figures. A change is an admin's or a fleet manager's, never an
agent's (403 PEOPLE_ONLY); it takes ?dryRun=true and an
Idempotency-Key, is in your audit trail, and sends ORGANIZATION.UPDATED
with change: "SETTINGS". Cypress's global rules are not yours to change
(404). Vehicles a rule already priced keep their prices.
A rule lists a car only when it is ready
Since 1.10.0. When a rule's outcome is to approve and list a vehicle
(apply_pricing_rule, apply_pricing_rules with confirm: true), the
vehicle first passes the listing checklist the Launch button checks: its
location state, mileage and condition (a grade or a score), with the rule's
price as the asking price. Something missing, and nothing moves: the answer is
an error naming it (The rule would list it, but it is missing what every listing needs: mileage, condition) and the vehicle stays in review. Before
1.10.0 a rule listed it anyway.
The bulk preview (?dryRun=true, or confirm left out) says it ahead:
missing lists the checklist fields the vehicle lacks when the rule would list
it, and every answer that lists carries the offer lines the rule sets,
computedAutoAcceptAbove (offers at or above it are accepted) and
computedAutoDenyBelow (offers below it are declined), as the single apply
always did.