BLOG

WEB

7 MIN

When someone else's API says gone

On 2 November 2026 Polymarket retired the first version of its data API. Nobody announced it to this site, which is the normal way these things arrive. One morning every call this desk made to the old leaderboard route started answering the same way, and that way is worth reading carefully if you run anything that touches somebody else's server.

The code is not the interesting part

I re-ran the checks before writing this, from this machine, no key, no account. Three old addresses, all the same result:

data-api.polymarket.com/leaderboard?window=all   410
lb-api.polymarket.com/leaderboard                410
data-api.polymarket.com/v1/leaderboard           410

410 is not 404. A 404 means "I cannot find this now", which could be a typo or a temporary state. 410 means gone: the thing existed and the owner has deliberately removed it. It is a permanent answer and it is supposed to be treated as one. Most people never meet it because most things never leave.

The part that saved me time was the body. It is not an empty page. It is JSON, written as an instruction:

{"error":"Data API v1 has been retired",
 "migration":"https://data-api.polymarket.com/v2/",
 "docs":"https://docs.polymarket.com/api-reference/data-api/overview"}

And the retired subdomain says the same thing in plainer words:

lb-api.polymarket.com has been retired.
Use https://data-api.polymarket.com/v2/leaderboard instead.
READ THE BODY, NOT THE CODE A 410 with a JSON message naming the replacement is a migration notice. A 410 with an empty body is a shutdown. Same status, completely different afternoon. The body is the first thing worth reading and most clients throw it away.

The replacement answers normally. The new route returns rows with a rank, an address, profit, volume and an optional username, and the response carries a cursor for the next page, so a loop can walk the whole leaderboard rather than just the top hundred.

Why a status check tells you nothing

A health check that asks "did this page load" passes this outage completely, because the page is loading. The HTML is fine. The asset files are fine. What broke was a JSON call made inside the browser, after the page arrived. The only thing that changed was one number, and it was inside a fetch that failed quietly.

This is the same class of mistake this site already had once, from the other direction. Its static host answers 200 OK for paths that do not exist, so a status check said healthy while a page was blank. Now a page is fully intact and a status check still says healthy. In both cases the status code was telling me nothing because the status code was never the thing being asked about.

The check that actually catches both is the same: fetch the page, look inside it, and look for the content that depends on the outside service. If the desk says a number of wallets, assert a number. If a board says a number of markets, assert that. Failures then show up as wrong content rather than as a stopped process.

The reason this site did not break

The Perps desk reads prebuilt snapshot files from this domain, not Polymarket. A snapshot is a copy of the answer, taken at build time and shipped with the site. The server on the other end can retire, rename itself or go dark, and the page keeps showing yesterday's numbers instead of a spinner.

This is a deliberate design and not an advantage I got for free. It costs freshness: the board is only as current as the last build. In exchange, the failure mode changes from "the page is broken" to "the page is slightly old". Between those two, slightly old is the one a reader can live with.

live call        page breaks the moment the source changes      always current
snapshot         page keeps working, numbers age quietly        as fresh as the build

The bill that came due anyway

Snapshots move the failure from the reader to the builder. The page is fine, but the next time a snapshot is generated, the generator is the thing that gets a 410 and hangs or writes an empty board. It is a quieter failure because nobody is watching that script the way they watch the page.

So the rule is not "use snapshots and relax". It is that the build needs the same treatment as the page: refuse to publish a snapshot that came back empty or short, and say so loudly at the moment it happens. That check is the same empty result guard this site already applies to its music catalogue, where a failed read once published a page with no songs on it and no error to show for it.

What to do when this happens to you

  • Fetch the old URL by hand. Read the status and then read the body. A retirement notice usually names its replacement.
  • Treat 410 as permanent and 404 as unknown. Do not retry a 410 on a schedule; you are asking a closed question.
  • Log the body, not just the code. The message is the documentation the owner left for you.
  • Change the path, not the architecture. In this case the fix was one segment of a URL, which is the best outcome an outage can have.
  • Assert on content. Any check that would have passed while this was broken is not checking the right thing.

One person found this because a chat conversation about perps venues happened to include a line about the retirement. That is luck, not process. The process is having a check that reads what is on screen, so the next one is found by the site rather than by a helpful afternoon.