Callside Docs
Reference

API

The read model behind the desk: REST endpoints and a WebSocket over indexed chain state. It serves the same figures at every hour, because the desk never closes, and everything it serves can be re-derived from the chain.

What it is

The api is a Fastify service that reads live contract state per request and indexes contract events, prices, NAV and TVL snapshots into a local database for history. It is a pure read model: it signs nothing, holds no keys with write power, and every state transition it reports happened on chain first. The base URL depends on the deployment; the web app reads it from its NEXT_PUBLIC_API_URL environment variable, and every path below is relative to that host.

Units

Every numeric chain value crosses the wire as a decimal string to avoid JavaScript number precision loss. Money fields are USDG with 6 decimal places, prices carry 8 decimal places, per-second index values are WAD (18 decimal places), and rates are integer basis points. Convert on the client; the api never sends floating point.

REST endpoints

EndpointDescription
/healthLiveness check; returns ok plus the network the api serves.
/api/metaDeployment snapshot: network, chain id, contract and token addresses, per-asset margin configuration, and headline rate and vault parameters. The frontend boots from this and never reads deployment files itself.
/api/stateGlobal state: interest index and rates, vault NAV, utilisation, insurance, skim state and deposit cap, current prices and per-asset halt flags. There is no session or calendar block: the desk is open continuously, so there is no open or closed flag to serve.
/api/account/:addressFull margin picture for one account: collateral value, debit, equity, initial and maintenance requirements, account state, positions valued at the mark, per-asset buying power, call state (in call, raised at, deadline), frozen flag and staking discount.
/api/account/:address/activityThe most recent 50 indexed contract events touching the account, newest first, with block, tx hash and decoded arguments.
/api/vault/:addressCash vault position for one depositor: shares, value at current NAV, and any pending withdrawal request with its claimable time.
/api/prices/:symbol/history?hours=Price series for one asset, 8 decimal places, downsampled to at most 48 points. hours defaults to 24 and is capped at 45 days.
/api/tvl-history?hours=Two series in 6dp USDG: vault TVL and desk collateral custody, downsampled to at most 200 points each.
/api/vault-nav-history?hours=Trailing vault NAV series (WAD values), used by the UI for the 30 day NAV change.
/api/protocolProtocol revenue: every InterestSettled event with its tx hash, cumulative totals, and the live unswept protocol balance awaiting the sweep to the foundation treasury.
/api/stocksRobinhood Chain mainnet stock token tracker, independent of the chain the desk runs on, flagged with which tickers the desk lists.
/api/venue-quote?symbol&side&notional|qtyPreviews a venue fill against the oracle mark: mark price, fill price and the gap in basis points. Buys are sized by notional in 6dp USDG; sells take a qty in token units, or a notional the api converts at the mark. Returns a null fill when the asset is halted or the venue has no liquidity.

A shortened account response, the shape the desk overview is built from:

GET /api/account/0xf39F...2266

{
  "address": "0xf39F...2266",
  "cv": "25000000000",
  "debit": "12000181000",
  "equity": "12999819000",
  "im": "10000000000",
  "mm": "6250000000",
  "state": 0,
  "excessEquity": "2999819000",
  "maintenanceExcess": "6749819000",
  "usdgBalance": "0",
  "principalScaled": "11987421305672108440000",
  "principalCash": "12000000000",
  "accruedInterest": "181000",
  "frozen": false,
  "call": { "inCall": false, "raisedAt": "0", "deadline": "0" },
  "positions": [
    { "symbol": "AAPL", "qty": "50000000000000000000", "value": "11500000000", "class": 5 }
  ],
  "buyingPower": { "AAPL": "5999638000", "WBTC": "7499547500" },
  "stakingDiscountBps": "0"
}

The WebSocket

Connect to /ws on the same host and the api pushes a tick every few seconds (five by default, set by TICK_MS): the current interest index, the gross rate, the vault NAV and every asset price.

{
  "type": "tick",
  "ts": 1756742400000,
  "indexWad": "1001507893218472011",
  "grossRateBps": "550",
  "navWad": "1000214000000000000",
  "prices": { "AAPL": "23000000000", "WBTC": "6400000000000" }
}

The tick does not carry your debit. The client holds principalScaled from the account endpoint and computes the ticking figure locally, advancing the index between pushes at the gross rate per second:

debit(t) = principalScaled x indexWad(t) / 1e18

That is why the debit on screen moves every second while the socket only ticks every few: the socket re-anchors the index, the client extrapolates in between. The same rule is in the UI spec, section 9.

Trust model

Nothing the api serves is authoritative. Addresses come from the deployment the api loads, figures come from contract reads, activity and revenue come from indexed events that carry their tx hashes. Any claim on any page can be checked against the chain directly, and the api has no ability to move funds, change parameters or act for an account.