{"apiVersion":"1","name":"MUIndex","description":"A read-only index of MU* games whose data is measured rather than asserted. Every value carries the source it came from and when it was last confirmed.","generatedAt":"2026-09-07T21:01:00+00:00","licence":{"id":"CC-BY-4.0","name":"Creative Commons Attribution 4.0 International","url":"https://creativecommons.org/licenses/by/4.0/","attribution":"MUIndex (https://github.com/SharpMUSH/MUIndex)"},"routes":[{"method":"GET","path":"/api/openapi.json","returns":"OpenAPI 3.1 contract: parameters, response schemas and errors."},{"method":"GET","path":"/about/api","returns":"HTML usage guide and examples."},{"method":"GET","path":"/api/games","returns":"The listing. Same querystring as the site's facet panel; see /api/openapi.json for every parameter, including genre, language, protocol, sort and pagination. Archived games are excluded unless archived=true. Two states are never in it and archived=true does not lift them: an address an editor ruled out as not a game, and a game whose owners asked to come out. Both still answer at their own route."},{"method":"GET","path":"/api/games/{id-or-slug}","returns":"One game, by its immutable id or its current slug. A slug the game used to have redirects here permanently."},{"method":"GET","path":"/api/games/{id-or-slug}/presence","returns":"Measured presence over time. Takes grain=hour|day (default day), from and to as ISO 8601. A bucket nobody measured is absent rather than zero."},{"method":"GET","path":"/api/games/{id-or-slug}/availability","returns":"Reachability over time, as spans rather than samples. Takes from and to. Measured from one vantage point: a game we cannot route to may be running perfectly well."},{"method":"GET","path":"/api/feeds","returns":"The three liveness registers: newly discovered, went dark, came back."},{"method":"GET","path":"/api/feeds/discovered.rss","returns":"Newly discovered, as RSS 2.0."},{"method":"GET","path":"/api/feeds/went-dark.rss","returns":"Went dark, as RSS 2.0."},{"method":"GET","path":"/api/feeds/came-back.rss","returns":"Came back, as RSS 2.0."},{"method":"GET","path":"/api/dump/games.json","returns":"The whole catalogue, archived games included, streamed as one JSON document."},{"method":"GET","path":"/api/dump/games.ndjson","returns":"The whole catalogue, one game per line (NDJSON)."}],"notes":["id is an immutable GUID and never changes, including across a merge. slug is minted from the game's name and does change; every slug a game has ever had keeps redirecting.","Nothing is ever deleted. An archived game keeps its URL, its history and its place in the dump; state says what it is.","Every value carries provenance and age. measured means somebody observed it; declared means a game asserted it. Where they disagree, both are published.","Every bare value has its label beside it or in fields: playersNow is labelled by playersNowProvenance, codebase by codebaseProvenance, on the listing as well as on a game. A null label means we hold no such value, never that we lost track of where one came from.","A player count of null means we did not measure one. It is never a zero. playersNowState is measured, declared or unknown and always agrees with playersNowProvenance. The line is who read the number: a pre-login WHO and a connect screen are both text we parsed off the socket this probe and are measured; PLAYERS in MSSP is the game reporting a field it maintains, and is declared. source names which of the three it was.","reachable describes a socket we opened from one vantage point at intervals. It is not a claim about whether the game was running: a game with a routing problem to our host is unreachable and perfectly alive.","Per-codebase and per-protocol shares are publishable; an absolute population figure is not, and this API publishes none.","Every response carries a strong ETag over its exact bytes. Send If-None-Match and expect a 304.","Webhooks are deliberately not built. RSS is the whole of the notification surface."]}