Pricing
Cambridge TCG sets a price for every card we stock and every channel we sell on. The same card has up to seven different customer-facing prices at any moment — one for our own storefront, one for Shopify, one for eBay, one for Cardmarket, one for trade-in cash, one for trade-in store credit — plus an internal wholesale base that the others derive from. This page explains exactly how each number is computed.
Where this lives in code. The canonical implementation is atpackages/pricing/src/index.ts(functioncomputePrice). Channel constants are stored in thechannel_pricingtable on the wholesale RDS and edited via the admin Manager page. Daily snapshot cron lives atapps/wholesale/src/lib/price-snapshot.ts. Every price mutation appends tocard_price_change_log. When the formula changes, this page is updated in the same PR.
The two inputs
Every price starts from two numbers captured at the same moment:
- JPY listing price — what the card is listed at on CardRush, in Japanese yen. Read once a day, then frozen for 24 hours.
- GBP/JPY rate — our view of the exchange rate at the moment of capture. Stored alongside the JPY value, so that the rate used to compute today's prices is the rate we wrote them with — not the rate at the moment you happen to be reading.
From these two, we derive a third — the wholesale base:
baseGbp = cardrush_jpy / gbp_jpy_rateThis is what one copy of the card costs us before any margin, fee, VAT, or channel uplift. It is the same across all channels.
The channel multipliers
Each channel has six numbers that say how to translate the wholesale base into that channel's customer-facing price.
| Number | What it is | Example (cambridgetcg.com) |
|---|---|---|
marginMultiplier | Our gross-margin uplift. 1.08 = 8% on top of base. | 1.08 |
flatFeeSingles | Per-card flat fee for single cards. | £0.22 |
flatFeeSealed | Per-product flat fee for sealed product. | £2.20 |
vatMultiplier | UK VAT multiplier. 1.20 = 20%. | 1.20 |
retailMultiplier | Channel-specific retail uplift. | 1.15 |
roundTo | Final rounding step. | £0.10 |
The full formula:
exVat = (baseGbp × marginMultiplier + flatFee) × retailMultiplier
vat = exVat × (vatMultiplier - 1)
preRound = exVat + vat
price = round(preRound / roundTo) × roundToThe final round uses banker's-style nearest-rounding (JavaScript's Math.round); a preRound value of £5.14 with a roundTo of £0.10 yields £5.10, not £5.20.
The eight channels
| Channel | Margin × | Flat singles | VAT × | Retail × | Round |
|---|---|---|---|---|---|
| wholesale (B2B base) | 1.08 | £0.22 | 1.20 | 1.00 | £0.01 |
| cambridgetcg.com (Next.js) | 1.08 | £0.22 | 1.20 | 1.15 | £0.10 |
| Shopify | 1.08 | £0.22 | 1.20 | 1.15 | £0.10 |
| eBay | 1.08 | £0.22 | 1.20 | 1.25 | £0.10 |
| Cardmarket | 1.08 | £0.22 | 1.20 | 1.20 | £0.01 |
| Trade-in (cash) | 0.55 | £0 | 1.00 | 1.00 | £0.01 |
| Trade-in (store credit) | 0.77 | £0 | 1.00 | 1.00 | £0.01 |
The trade-in channels invert the margin: we pay 55% of the wholesale base for cash, 77% for store credit. They have no flat fee, no VAT (we are the buyer, not the seller), and no retail uplift.
The retail channels (cambridgetcg, Shopify, eBay, Cardmarket) all charge VAT. The retail multiplier differs: eBay's is highest because eBay's seller fees are higher and we recover them via the price.
Worked example
A ¥600 listing today (¥/£ rate = 185):
baseGbp = 600 / 185 = £3.24
cambridgetcg.com:
exVat = (3.24 × 1.08 + 0.22) × 1.15 = £4.28
vat = 4.28 × 0.20 = £0.86
preRound = 4.28 + 0.86 = £5.14
price = round(5.14 / 0.10) × 0.10 = £5.10The same listing on eBay produces £5.60; on trade-in cash, we pay £1.78 to take it off your hands; on trade-in store credit, £2.50. These exact numbers are locked as regression tests in packages/pricing/src/__tests__/pricing.test.ts — if the formula drifts, the tests fire and this page is updated in the same PR.
Freshness
Prices are snapshot daily at 02:00 UTC. The catalog you see on a typical visit was true at the most recent snapshot. Every price surface on cambridgetcg.com displays a small label like "synced from wholesale · 4h ago" next to the price — this is the freshness pill, and it tells you exactly when the number you're looking at became true.
If the snapshot cron fails or hasn't run yet, the pill turns amber. If the wholesale source is unavailable entirely, the pill turns red and reads "source unavailable". We do not show stale prices as if they were live.
What changes a price
- The daily snapshot found a new CardRush price. Most common. The cron at 02:00 UTC scrapes CardRush, pairs it with the current exchange rate, runs the formula, and writes a new row. Logged with
action = "snapshot". - An admin edited the price manually. Rare. Logged with
action = "admin_edit"and the operator's email. - The CSV upload sync ran. Bulk imports through the admin CSV path produce the same effect as a daily snapshot for the affected cards.
- The exchange rate moved overnight. Even if the JPY price is unchanged, a different rate produces a different GBP base.
What does not affect a price
- Who is looking at it. Every customer sees the same price for the same channel.
- Stock level. Low-stock cards do not auto-mark-up; high-stock cards do not auto-discount.
- Account standing or trust score. These affect commission and escrow routing, not the retail price.
- Membership tier. Tier perks include cashback and points multipliers; the listed price is the same regardless of tier (your cashback / points adjustment lands separately).
Verifying a price yourself
Every price on cambridgetcg.com is reproducible from:
- The CardRush JPY listing you can navigate to from the card detail page.
- The GBP/JPY rate on the snapshot date.
- The cambridgetcg channel constants in the table above.
- The formula above.
If a price doesn't match what this formula would produce — within £0.01 rounding tolerance — that's a bug. Email us at [email protected] with the SKU and the snapshot date and we'll investigate.
Open changes
Some pricing aspects are still in motion. We name them rather than hide them:
- Vault sell-back values are frozen at acquisition. When you redeem a bounty pull into your vault, the sell-back-to-store-credit price is locked at that moment's spot. If the market moves, your frozen value does not move with it. This is intentional today; we may revisit.
- Channel parity is operator-set, not algorithmic. The eBay-vs-cambridgetcg-vs-Shopify multiplier difference is policy, not derived.