What you’ll get
Every recorded version of one market’s contract terms with what changed between them, the rulebooks in force above it with their settlement sources, and a live feed of rule changes across every market. Then a checklist for the case that matters most: the terms a position or a proof rests on changed underneath it. On 2026-09-17 a Polymarket election market’s resolution metadata changed at 12:01 UTC, and a Kalshi tennis market’s strike and close time changed at 12:03.Prerequisites
- An API key in
ROUTEUR_API_KEY - Python 3 with
requests
1
Read a market's rules and their history
GET /v1/markets/{venue}/{id}/rules works for any market ever recorded, listed or not.rules, left out here):umaResolutionStatuses went from [] to ["proposed", "proposed"]: a resolution has been proposed on UMA, and the market is about to settle.2
Print the versions, diffs and settlement sources
This script lists every contract version with its diff, the rulebooks in force with where each says the market settles, the ledger, and then reads each rulebook’s own history to say whether a settlement source changed.Output for the Polymarket market above, observed 2026-09-17 12:48 UTC:And for a Kalshi market whose own contract changed, the same script:
Python
3
Follow rule changes as they happen
The An event observed 2026-09-17 12:03 UTC (replayed with a cursor from earlier in the hour):Set Between 12:01 and 12:36 UTC on 2026-09-17, 699
rules topic of /v1/stream sends one rule_change event per change, for every market or only the ones you name in markets.TOPICS = "rules" in the Stream consumer and replace its handler with one that keys on what changed:Python
rule_change events arrived, 695 of them on Polymarket. 574 had changed_fields: [] (a term the recorded fields do not show, mostly resolution timestamps moving as games ended), 46 changed only game_starts_at, and 79 changed strike or closes_at. The last group is the one a position cares about; the handler above marks it TERMS or TIMING.4
When the settlement source changes
A settlement source is where the venue says it will read the result. It lives in the rulebooks above the contract: a Kalshi event’s
settlement_sources, a Polymarket market’s resolutionSource and umaResolutionStatuses, and the venue’s contract terms document. A change there does not change the market’s rules_hash, so it is easy to miss. When the stream sends a rule_change with scope other than contract, or the rulebook’s changed_fields names a source, do this:- Read the diff.
GET /v1/rulebooks/{venue}/{kind}/{id}has every version withchanged_fields,diff, and for Kalshi the termsdocumentwith its owndiff. Decide whether the new source can disagree with the old one. - Re-check every proof the market is in. A proof holds for a contract version, and a relation’s evidence names what both contracts settle on.
GET /v1/relations/{a}/{b}returnsreproduced: false, or404 relation_not_found, when the graph can no longer relate the current versions; a relation that survives is safe only if itsevidencestill describes the settlement you read in step 1. - Treat leads on the pair as void until the next graph run confirms them. Runs finish hourly (
GET /v1/status), and a lead’sdepth.limited_bybecomesinformationalwhen the venues could settle differently. - If you hold a position, compare the sources, not the hashes. The script’s last section prints
SETTLEMENT SOURCE CHANGEDwith the names before and after. A change from a named agency to none, or to a different one, is the case to act on.
umaResolutionStatuses going from [] to ["proposed", ...], as above, is not a source change: it means resolution has started on the same source. Expect the market to close and the price to go to 0 or 100¢.Read the result
Pitfalls
changed_fields: []with a new hash is normal. It means the venue changed something the recorded fields do not show, such as an expiration or settlement timestamp. The summary says so. Do not treat every new version as a rules rewrite; do read the ledger when one lands on a market you hold.- Kalshi series rulebooks were not recorded on 2026-09-17.
GET /v1/rulebooks/kalshi/series/KXBTCD(andKXMLBTOTAL,KXSB,KXITFMATCH) returned404 rulebook_not_found; onlyeventrulebooks were present. The script skips a missing rulebook; the series’ contract terms document is then not available through this endpoint. - A close time moving earlier is a settlement. The Kalshi tennis market’s
closes_atmoved from 2026-10-01 to 2026-09-17 12:00:40 because the match ended. Treat it as the market resolving, not as a rule change to argue with. - Hashes are 64 hex characters. The script prints 12 for readability; compare full values in code.
- The stream replays one hour. A watcher that was down longer must reread
/rulesfor the markets it cares about after theresetevent.
Related
- Proof trail: the proof names the contract versions it holds for.
- Stream consumer: a resumable consumer for the
rulestopic. - Venues: how each venue publishes its terms.
GET /v1/rulebooks/{venue}/{kind}/{id}: every version of a rulebook and the markets under it.