net_backend

API reference

Building a client

Tokens

  • Store the whole TokenPair (both tokens and both expiry times); keep it until a new pair is stored.
  • Refresh when less than 60 s of the access token are left (compare access_expires_at with the clock), and on any 401 token_expired (then retry the request once).
  • Refresh single-flight: one refresh at a time per refresh token, across every tab, window or thread that shares it. A second use within 30 s answers the same pair; a later reuse logs the player out everywhere (refresh_token_reused).
  • On 401 unauthorized / refresh_token_reused or 403 banned from refresh: drop the tokens and show the login screen. On network errors and 5xx: keep them and try again later.
  • Log out with the refresh token in the body, so logout works after the access token expired.
  • In a browser, tokens in localStorage are readable by any script on the page: keep the page free of untrusted scripts (or keep the tokens in memory and log in per visit).

HTTP

  • Send Content-Type: application/json and a JSON body ({} at least) on routes with a body.
  • Branch on error.code, never on message; treat unknown codes like their HTTP status.
  • On 429 wait details.retry_after_ms (or Retry-After); on 503 retry with backoff.
  • Use if_version for saves that two devices may write.
  • Ignore unknown fields; treat absent and null the same.
  • Optionally send x-net-backend-protocol: 1 and check GET /v1/info at start-up (min_protocol ≤ your version ≤ protocol, and the modules you need).

WebSocket

  • One connection per client; authenticate with the header or the first-message auth within 5 s; send requests only after auth.ok.
  • Number requests with a counter; match answers by id; every request gets exactly one answer.
  • Classify frames: numeric id and (ok or no type) = answer; otherwise by type (auth.ok, auth.failed, pushes). Ignore unknown push kinds.
  • Never reconnect automatically after 4000–4099 (4001: one refresh + one new connection at most). Reconnect with exponential backoff and jitter after everything else (1000, 1001, 1006, 1008, 1009, 1011, 1013).
  • After every (re)connect: join the chat rooms again and reload what may have been missed.
  • Do not resend chat.send automatically; use a random nonce and dedupe by message id.
  • Keep messages under 1 MiB and below 20 frames per second (burst 40).
  • Answer pings (browsers and most libraries do it for you); expect the server to drop a connection that is silent for 60 s.
  • At most 5 connections per user: a 6th closes the oldest with 4009 (tell the player).

What to persist between runs

  • The TokenPair (secret: store it like a password).
  • Optionally the account (id, display_name) for an instant start, refreshed with GET /v1/account.
  • The storage versions you last loaded or wrote, when the game keeps local copies of saves.
  • Nothing about WebSocket state: room membership and presence are rebuilt after every connect.

Generated from API.md (repository commit e25edb9, file sha256 3db87f7bba70).