Product document · the build concept

Stock Hub — the inventory spine

One piece of software that owns the stock and links Trade Me ↔ Shopify: list a unit once, it sells once, and it's withdrawn everywhere. The product concept, the modules, and the one thing every off-the-shelf tool gets wrong.
Single source of truth Unique-unit sync (not qty sync) Build, don't buy Candidate product: StockLoop
Product concept v1 · 11 June 2026 · modelled on 3Dsellers, Linnworks, Finale, Sellbrite, Omnivore, Tradevine · Shopify Admin GraphQL + Trade Me API.

1 The product in one line

A single piece of software that owns your stock, and pushes it out to — and pulls sales back from — Trade Me and Shopify automatically. One unit of stock, listed everywhere, sells once, disappears everywhere.

It's the thing eBay sellers buy off the shelf (Linnworks, 3Dsellers, Finale) — except no one sells a good version for Trade Me + Shopify in New Zealand. So we build it. For TYDI it's the operating system. Beyond TYDI, it might be a product (§9).

2 What we're modelling it on — and why we build, not buy

Reference toolBest atWhat we borrow
Linnworks (inventory-hub gold standard)Central catalogue → many channels, real-time sync, unified ordersThe engine architecture — hub-and-spoke, single source of truth
Finale Inventory (refurb specialist)Per-unit IMEI/serial tracking, condition grading, one-of-a-kind stockThe data model — every physical unit is its own record
3Dsellers (top eBay all-in-one, ~200k sellers)AI listing creation, templates, bulk editor, repricer, feedbackThe listing intelligence — templated, AI-drafted, bulk-managed
Sellbrite (single-operator simplicity)The 80/20 subset for a solo seller, not a 100-channel enterpriseThe scope discipline — keep it lean

Why build instead of buy

The gap that matters most: all the cheap tools do quantity sync — they don't do unique-unit sync. That distinction is the heart of the product (§4).

3 The core concept — the Hub as single source of truth

The Stock Hub · master catalogue (Postgres)
1 physical unit = 1 record
qty 1 · grade · serial/IMEI · cost · status · photos
Trade Me
  • Selling API
  • poll sales every 60–120s
Shopify
  • Admin API
  • webhook on sale (instant)
↓ SOLD ON ONE → WITHDRAWN ON THE OTHER ↓

The rule that makes it work: the channels never talk to each other — they only talk to the Hub. A sale anywhere updates the Hub, and the Hub updates everywhere else. Add eBay AU or Reebelo later and it's just another spoke — the Hub doesn't change.

4 The one thing off-the-shelf tools get wrong (our make-or-break)

Generic tools assume…

"5 identical widgets." When one sells, they decrement 5 → 4. Fine for commodity stock.

Refurb electronics are…

"5 different physical phones, each unique, each qty 1." When phone #X sells, there's no "4 left" — there's a different phone. You must withdraw that exact listing entirely.

This is listing-withdrawal sync, not quantity sync — precisely where Sellbrite/Codisto-class tools break and oversell. Getting it right is the core of the build. Every unique unit = one Hub record (qty 1) → one Trade Me listing + one Shopify listing, all linked, all withdrawn together the instant it sells anywhere.

(The Hub also handles normal multi-quantity stock — accessories, parts, new-old-stock — as ordinary qty pools. But the unique-unit case is the differentiator.)

5 What it does — the modules

Ordered as a product, front-door to back-office.
Module 1 — the front door
Intake & Grading

Scan the device → capture IMEI/serial, grade (A/B/C), battery health, cosmetic notes, photos, cost, supplier. Hub auto-mints a SKU (IPH13-128-BLK-A-{serial}) + master record. Where refurb businesses live, and where generic tools have nothing.

Module 2 — single source of truth
Master Catalogue

One record per physical unit, qty 1, with a parent "model" grouping. Status flows: in-stock → listed → sold → dispatched → (returned → re-graded → re-listed). Everything reads from here.

Module 3 — the photo→listing pipeline, slotted in
AI Listing Publisher

Clean photos (PhotoRoom), vision-LLM drafts the title (leads "Refurbished"), fills attributes, writes the description + subtitle, suggests a price. One template per product line. Batch-approve → publish to Trade Me and Shopify in one action.

Module 4 — the link, the heart
Multichannel Sync Engine

Shopify → Hub: orders/paid webhook (seconds) → withdraw on Trade Me. Trade Me → Hub: poll sold-items every 60–120s → set Shopify to 0 / unpublish. Oversell safety: atomic claim, compare-and-set, reconciliation poll (§7).

Module 5 — back office
Unified Orders & Dispatch

Every TM + Shopify order in one queue, resolved to the exact serial. Scan-to-confirm on pick (scanned IMEI must match). NZ carrier labels (Starshipit / GoSweetSpot / NZ Post). Tracking pushed back; listing withdrawn on the other channel.

Module 6 — the lifecycle tools fail at
Returns / Re-grade / Re-list Loop

Return received → inspect → re-grade (may downgrade) → re-price → re-list as a fresh qty-1 record. An explicit state machine so units never get stuck as ghost stock.

Module 7 — the decision layer
Reporting & Per-Unit Margin

Because every unit is serialised with its cost, true per-unit profit (sale − cost − fees − shipping) is trivial — plus days-to-sell by model/grade, ageing-stock alerts, sell-through by channel.

Phase-2 modules (defer): Q&A auto-responder, feedback automation, age-based markdown repricing, Sponsored Listings management. All supported by the Trade Me API; none are day-one critical.

6 How it all comes together — one phone's journey

A refurbished iPhone 13 arrives

Operator scans it: IMEI captured, graded B, battery 89%, small scuff, 4 photos, cost $380. → Hub creates IPH13-128-BLK-B-{serial}, qty 1, status in-stock.

AI Publisher drafts the listing

Title "Refurbished Apple iPhone 13 128GB Black — Grade B, 89% Battery, 12-Month Warranty", attributes filled, price $620. Operator approves. → Live on Trade Me and Shopify, linked.

It sells on Trade Me at 2:14pm

Next poll (≤2 min) the Hub sees the sale → marks sold → sets the Shopify listing to 0 / unpublishes it. The website can no longer sell the same phone.

The order drops into the unified queue

Operator picks it, scans the IMEI — matches ✓ — prints a CourierPost label, packs. → Hub marks dispatched, pushes tracking to Trade Me, marks shipped via the API.

Per-unit margin booked automatically

Sold $620 − cost $380 − TM fee − shipping = real profit on that exact device, in the dashboard.

(If returned)

Inspect → maybe re-grade to C → re-price → the Hub spins up a new qty-1 listing. Loop closed.

Steps 2–4 are ~90% software. The human scans the box at intake and tapes it at dispatch. That's the whole "AI-first" promise made concrete.

7 The Trade Me ↔ Shopify link — how the sync really behaves

The honest engineering picture, because this is the part that's genuinely hard.
DirectionMechanismSpeedReliability move
Shopify → Trade Meorders/paid webhook → ack <1s, queue the job, withdraw on TMSecondsVerify HMAC; process async; reconciliation poll as backstop
Trade Me → ShopifyPoll SoldItems (LastHour) every 60–120sUp to ~2 mininventorySetQuantities with compare-and-set so the Hub never overwrites a unit Shopify just sold
The unavoidable truth: Trade Me has no webhooks, so TM sales are only knowable by polling. That creates a small oversell window for a unique unit listed on both channels — a website buyer could grab the same phone in the ~2-min gap. Low probability per item, but high cost per incident (refund + reputation hit on the 99.16%-feedback account that is the asset).

Mitigation, in order of strength

It can't be closed to zero — but for a refurb business it can be made rare and cheap, and policy (1) makes it a non-issue for the stock that matters.

Acknowledge the trade-off, though. Policy (1) works by not dual-listing the unique high-value units — which means it reduces the multi-channel listing this Hub exists to enable. So the Hub's clearest, unambiguous value is the AI listing pipeline plus commodity / multi-quantity stock (accessories, parts, new-old-stock as ordinary qty pools), where dual-listing carries low oversell risk. Reserve dual-listing for that low-risk stock; route premium qty-1 units to a single channel. The Hub still earns its keep — the listing engine and the commodity multichannel reach are the bulk of the value — but the "list once → sell on every channel" line is, by design, narrowed for the unique units where the oversell race actually bites.

8 Build vs buy — the call

Omnivore/TradeRunner exists and does Shopify↔Trade Me today. So why build?

Recommendation: build it for TYDI. Use Omnivore only as a stop-gap if you want stock synced before the Hub is ready.

9 The bigger idea — could this be a product?

The instinct is right but needs calibrating. The honest read: the white space is real but thin — a niche, not a land-grab.
~25k
Active Shopify stores in NZ (~3,100 in Canterbury), growing ~9%/yr
low-000s
Realistic overlap — sellers running both Shopify + a serious Trade Me store
$49–99
/mo — a small, defensible SaaS; low-hundreds-of-$k ARR ceiling, not a venture outcome
The smart sequencing (the actual "something cool"): build it for TYDI first, where it pays for itself as the operating system on a real high-volume store. TYDI becomes the proof-of-concept and first case study. Then the productisation decision is de-risked — you've already built and battle-tested it. "Build for one, sell to many," but only commit to the "many" after the "one" proves it. Exactly your SettledLoop pattern. Treat productising as optional upside on a build justified for TYDI alone.

10 Phased build (mirrors the data dependency)

PhaseShipsWhy this order
1 — Catalogue + IntakeMaster record model + the scan/grade front doorGet the data model right first; everything hangs off it
2 — AI Listing PublisherPhoto→listing pipeline → publish to TM + ShopifyThe 80/20 of value; fixes every CRO gap
3 — Sync EngineUnique-unit withdrawal sync, both directions + safety netProtects the listings once live; the make-or-break module
4 — Orders + DispatchUnified queue, scan-to-confirm, NZ labels, tracking pushbackRecovers the daily fulfilment grind
5 — Returns loopRe-grade → re-list state machineCloses the lifecycle the tools fail at
6 — ReportingPer-unit margin, ageing, sell-throughThe decision layer
Phase 2+Q&A bot, feedback, repricing, more channelsLeverage once the spine runs

Built on your stack: Node/Fastify/Postgres/Prisma/Railway, secrets in ~/.brain-secrets/, Shopify custom app (GraphQL Admin API), Trade Me OAuth 1.0a app (register fresh under the new in-trade owner — see the API doc's §2).

11 Decisions for you

1. Scope — full Hub, or just the AI Listing Publisher bolted onto Omnivore for sync, build the sync engine later? Lean: catalogue + publisher first (the value); add the sync engine before you trust it for unique units.
2. Channel-routing policy — dual-list everything, or route unique high-value units to one channel? Lean: route high-value to one channel — kills the oversell risk where it matters.
3. Productisation — TYDI-only for now, or design multi-tenant from day one? Lean: TYDI-first, but keep tenant-isolation in the data model so productising later isn't a rewrite — the SettledLoop lesson.
4. Pre-settlement — want a Phase 1+2 build brief (data model + enrich prompt + approve-screen wireframe) ready to start in the sandbox before settlement?
Grounded in June-2026 product research and the Shopify/Trade Me API docs. Endpoint behaviour, Tradevine's Shopify status, and competitor pricing should be re-verified at build time. Not legal advice — confirm Trade Me API T&Cs (no caching/redistributing their data) for any competitor-facing feature.
→ See the full operating-system vision (Stock Hub)
← Back to the document hub