DEV Community

FairStash
FairStash

Posted on

What 1,550 listings actually measure: turnover, not stock

Every value list for a Roblox trading game answers the same question: what is this item worth? We wanted a different number — how many people are actually offering one right now — and the marketplace we read has an endpoint that looks like it gives exactly that.

It does not. Here is what it gives instead, and how we measured the difference.

The endpoint

Traderie hands out listings a page at a time:

/api/<game>/listings?limit=100&page=N
Enter fullscreen mode Exit fullscreen mode

Two things are missing, and both matter:

  1. There is no total count. No total, no count, no Link: rel="last". You page until it stops.
  2. It stops early. Every game we tried caps out at the same place: 1,550 listings, 31 pages. Ask for page 32 and you get nothing. limit is honoured on the plain endpoint and silently ignored on the filtered one, which always returns 50.

So you get the 1,550 most recently updated listings. Not a sample — a window, sorted newest first.

The mistake we shipped

We counted how many of those 1,550 listings mentioned each item and published the result as "how many people are offering one". That reads as a stock measurement: this many exist for sale right now.

It is not. It is however many happened to be touched inside the window — and the window is a duration, not a quantity.

Measuring the window

Each listing carries updated_at. The oldest and newest in a completed run bracket exactly how much time those 1,550 listings covered. That is a free measurement: the data is already in the response.

let from = null, to = null
for (const listing of page) {
  const t = Date.parse(listing.updated_at)
  if (!from || t < from) from = t
  if (!to || t > to) to = t
}
// window in minutes
const minutes = Math.round((to - from) / 60000)
Enter fullscreen mode Exit fullscreen mode

Run on 2026-09-09, three games on the same platform:

Game Window covered by 1,550 listings
Flee the Facility 14.3 hours
Murder Mystery 2 69 minutes
Adopt Me 18 minutes

The same cap means wildly different things depending on how busy the game is. On the quiet game the window is most of a day. On the busy one it is a coffee break.

The check that settled it

If the count were stock, an item recorded as 0 would have nothing on offer. So we asked per item, using the filtered endpoint:

/api/<game>/listings?itemTags=true&item=<id>&selling=true&auction=false&page=N
Enter fullscreen mode Exit fullscreen mode

Of thirty Adopt Me items sampled, twenty-eight had at least fifty active listings — including items our file had recorded as 0 that day. One item had at least 1,550 standing offers while appearing zero times in the newest 100.

Zero in the window is not an observation of absence. It is an absence of observation.

What the number actually is

It is turnover: how often an item moves through new listings. With the window duration measured alongside it, that becomes a rate — listings per hour — comparable between days and between games.

And turnover discriminates where stock does not. Two MM2 items both answer "300+ active listings" to the exact query; inside the window one appears 51 times and the other zero. The expensive exact count is the less informative number.

The cost of getting it exactly

We priced the honest alternative before rejecting it: one request per item per page, 50 per page, for a catalogue of thousands — up to 33,000 requests a day, and the answer would still be "300+" for most items. Not worth it, and not kind to someone else's servers.

Open data

The daily counts are published under CC BY 4.0, one row per item per day, with the window duration recorded beside each reading so the caveat can never outlive the data:

If you are reading a marketplace API that caps its result set, the lesson generalises: check what duration your cap covers before you name the number. A count with an unmeasured window is a sentence with an unknown subject.

Top comments (1)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.