Newman logo
NEWMAN
API RESPECT

For Synthriderz operators

How Newman uses your public API

Newman is an unofficial fan tool. It reads public Synthriderz JSON only — no scraping HTML, no accounts, no write endpoints. This page is the load + mitigation statement we want you to be able to point at before anything goes broadly live.

What we call

  • GET /api/leaderboards/profile/{user} — profile stats (once per player, cached)
  • GET /api/scores?…&pb=1&limit=100&page=N — personal bests with embedded leaderboard metadata (paginated)
  • GET /api/leaderboard-profiles?s=… — player autocomplete / existence checks (short queries, limit ≤ 20)
  • GET /api/leaderboards/{id} — occasional beatmap-id resolve for leaderboard deep links (lazy, not on the ingest hot path)

User-Agent: newman-sr/1.0 (+https://github.com/heavygee/newman.rip)

Load we put on Synthriderz

  • A cold pull for a heavy player is on the order of tens of score pages (100 PBs per page). Two players ≈ two of those crawls.
  • Autocomplete hits leaderboard-profiles while someone types (debounced ~ 250ms on the client; still subject to our server rate gate).
  • Manual refresh is allowed, but cooldown-gated per player (default 15 minutes).

How we mitigate

RuleWhat we do
No parallel upstream fan-outOne global fetch queue. At most one Synthriderz-touching job runs at a time (Postgres claim + SKIP LOCKED).
≥200ms between callsServer-side rate limiter (SYNTHRIDERZ_MIN_DELAY_MS, default 200). Sequential pages only.
Cache firstPBs cached in Supabase (default 24h). Profiles cached (default 6h). Repeat visits serve from cache — zero upstream if warm.
Stale-while-revalidateIf we already have PBs, we show the last report immediately while a refresh drains in the background — so users stop hammering refresh.
Incremental jobsScore pulls are paginated job ticks (usually 1 page per tick). Vercel functions never try to download an entire catalog in one request.
Short cron drainsQueue kicks budget ~45s on Hobby so we return cleanly; a host timer retries every 2 minutes instead of one long scrape.
No beatmap resolve on ingestScore pages upsert without resolving every leaderboard→beatmap id up front (that used to multiply API calls per page).
Player validationHome autocomplete only starts a rivalry for names that exist in leaderboard-profiles — fewer accidental crawls of typos. Uses Synthriderz nestjsx-crud $startsL / $contL / $eqL.
Honest identityIdentifiable User-Agent pointing at the GitHub repo. No browser impersonation.

What we do not do

  • No login, cookies, or session hijacking
  • No POST/PUT/DELETE against Synthriderz
  • No HTML scraping of the site
  • No selling data; private fan app (not a commercial product)
  • No LLM rewriting of scores — compare math is deterministic over cached rows

Contact

If Synthriderz operators want a lower rate, a allowlist, or for Newman to stop: open an issue on github.com/heavygee/newman.rip or message the maintainer (HeavyGee / Gavin). We will honor a clear request to throttle or shut off.

Live app: newmanrip.vercel.app. This page: /respect.

← Back to Newman