{
  "service": "postmortem",
  "what": "scores every finished trade against the plan and against what happened; the gap is the trader delta",
  "url": "https://api.slowdesk.io",
  "auth": "every route below except / and /health needs an API key: `Authorization: Bearer pm_…` or `X-API-Key: pm_…` on REST, `?key=pm_…` on a socket. Scopes: read, replay, score.",
  "docs": "docs/using-the-api.md in the repo",
  "rest": {
    "GET  /health": "liveness and what is configured",
    "GET  /me": "the key you are using, and its scopes",
    "GET  /rides/:id/score": "score one ride now (hits Databento; seconds)",
    "GET  /scores?from&to&limit": "stored scores, newest version of each ride",
    "GET  /scores/:rideId": "the newest stored score for one ride",
    "POST /score/range {from,to}": "start a scoring job; listen on the socket",
    "GET  /jobs": "jobs this process knows about",
    "GET  /jobs/:id": "one job, with its scores",
    "GET  /ticks/manifest.json": "the replay tape's coverage: per symbol, the session dates on file, rows per channel, first and last ts",
    "GET  /ticks/day=YYYY-MM-DD/symbol=XXX/ticks.ndjson.gz": "one symbol-day of trades, quotes and status — the same object as in S3 (tradingdesk#777)",
    "GET  /ticks/day=YYYY-MM-DD/symbol=XXX/manifest.json": "that day's own summary and sha256",
    "POST /ticks/warm {symbols, day}": "pull those symbol-days into the local cache so a replay starts without waiting on S3"
  },
  "replay": {
    "url": "ws://<host>/replay?symbols=AAPL,SPY&day=2026-09-02&from=09:25&to=16:05&speed=1",
    "what": "the archive played back at tape pace: what slowsocket's socket would have delivered that day",
    "params": {
      "symbols": "comma list",
      "day": "YYYY-MM-DD (ET session)",
      "from": "HH:MM New York or ISO; default 04:00",
      "to": "default 20:01",
      "speed": "1 = real time, 10 = 10x, 0 = as fast as the socket drains"
    },
    "frames": [
      "hello",
      "loading",
      "snapshot (per symbol: the quote, trade and status standing at `from`)",
      "ready",
      "rows (each has `channel`; no `type`)",
      "clock",
      "end"
    ],
    "control": "send {op:'pause'} | {op:'resume'} | {op:'speed', speed:10}"
  },
  "ws": {
    "url": "ws://<host>/ws",
    "events": [
      "job.started",
      "job.progress",
      "score",
      "job.finished",
      "job.failed"
    ],
    "why": "a range run takes minutes, and nightly scores arrive after midnight ET when the data licence advances"
  }
}