Open data
Outranked.me publishes its leaderboard and its complete change history as open JSON, free to use under CC-BY-4.0. Right now that is 0 ranked listings, 0 recorded position changes, and 0 businesses that have proved they control their own domain.
Why this data is unusual
Most directory rankings are editorial, which makes them unfalsifiable — you cannot check an opinion. This one is arithmetic over verified payments, and the arithmetic is published. Rank is one plus the number of listings with greater time-weighted verified spend, computed on read and never stored, so there is no rank column anyone could edit. The change history is written inside the same transaction that applies the money, which is why it can name the listing that caused each displacement rather than inferring it afterwards.
Endpoints
GET /api/v1/rankings
?limit= (max 250) and ?offset=. The response includes the live methodology — model, half-life and floor — so the data always travels with the rule that produced it.Pass
?scope= for a single board rather than the global one: category:<uuid>, country:<cc>, industry:<uuid>, city:<uuid>, state:<uuid>, subcategory:<uuid>, or the composite country_category:<cc>:<uuid>. An unrecognised scope is a 400, not a quiet fall back to the global board — answering a different question than the one asked is how a citation ends up pointing at the wrong leaderboard.GET /api/v1/changes
?limit= (max 200) and ?offset=. Also available as an Atom feed.?from= and ?to= as ISO 8601 timestamps and ?limit= (max 500, default 168 — one week).A rank of
null means the listing held no position in that scope at that hour. It is never reported as zero, because a zero would plot as a position that never existed. A missing hour means the snapshot job did not run then, not that the listing was absent.This is the series that is hardest to stage: each row was written by a scheduled job at the hour it names, and a unique constraint on listing and hour means a row cannot be rewritten later to tell a better story.
Reading the numbers correctly
- Amounts are minor units of USD —
413900means 4,139.00, not 413,900. - Spend is time-weighted. A payment counts fully when made, then halves every 7 days, never falling below 10% of its original value. So
ranking_scoreis not lifetime spend, and a position has to be maintained. - A change row has no payment amount, and deliberately claims none. The record links a movement to a cause, not to a receipt; a displaced listing stores no score at all, so the API returns null rather than zero.
- Verified means ownership, not quality. It says the operator proved control of the domain. It is not an endorsement and it is independent of position.
- Refunds unwind. Refunded money stops counting and the board recalculates, so a historical figure and a current one can legitimately disagree.
Using it
Free for any use, including commercial, with attribution to Outranked.me. Responses carry a strong ETag, so a polling client should send If-None-Match and will get a 304 when nothing has changed — that is the cheap path for both of us, and there is no rate limit on it. Cite the methodology_version from the payload rather than the date you fetched it: when the ranking rule changes, that version is how a historical figure stays interpretable.
The full rule set is on the methodology page, which is generated from the same live configuration these endpoints report.