Skip to main content
Learn how to put token theses on your price chart. Every thesis is written by a verified holder of the token, so a marker on the chart shows when a real holder called it, whether they were bullish or bearish, and how their position is doing now. Hover a marker to read the thesis. This recipe loads the existing theses once, then keeps the chart live with the theses stream. It targets TradingView Lightweight Charts 5.0.8 (createSeriesMarkers), in plain JavaScript.

What you will build

A candlestick chart with one marker per thesis: green arrow below the bar for bull, red arrow above the bar for bear, grey circle without a stance. The label reads @author +54%, the author’s live PnL on the token. New theses appear the moment they are posted, deleted or hidden ones disappear.

How it fits together

Your API key must never reach the browser. A tiny relay on your server holds the key, loads the history and keeps one connection to the theses stream. The browser only talks to the relay.
The endpoints used:

GET /v1/theses

The theses of a token, with author, stance, created_at and position.

Theses stream

Live thesis events for up to 200 tokens per connection. Every plan.

Step 1, the relay

Node 22 or newer (global fetch and WebSocket), plus the ws package for the browser-facing socket: npm install ws. Set CABALSPY_API_KEY to your key with CabalSpy ID enabled. The relay keeps one upstream connection, subscribes to every token a browser is watching, and forwards each thesis event only to the browsers watching that token.
relay.mjs
The relay only accepts known chains and address-shaped mints, so nobody can use it to call other endpoints with your key. One upstream connection carries up to 200 tokens; open a second one if you show more.

Step 2, the chart

Load Lightweight Charts 5.0.8 and give the chart a container and a tooltip element.
index.html

Step 3, theses to markers

A marker needs a time, a position, a shape, a color and a text. The time must be a Unix timestamp in seconds, and markers must be sorted by time. Round created_at down to the bar interval so the marker sits on the right candle.
markers.js (part 1)

Step 4, draw, load and go live

Create the chart and the marker plugin, load the history from the relay, then apply live events. thesis adds a marker, thesis.removed deletes one. Hovering a marker shows the thesis body, using the marker id that Lightweight Charts reports as hoveredObjectId.
markers.js (part 2)
Call it with your own candles:
textContent keeps the thesis text as plain text: never insert it as HTML.

The same relay with the SDK

The JavaScript SDK (npm install cabalspy-id ws) wraps the stream in ThesesStream: it reconnects on its own, watches the heartbeat and sends your subscriptions again after every reconnect. Replace the upstream part and the history call of the relay with this:
relay-sdk.mjs
The browser code from steps 2 to 4 stays the same: /theses answers { data: [...] } and /live sends { event, data } messages in both versions.

Lessons worth knowing

Keep the key on the server. The relay is a few dozen lines and is the only thing that ever sees your API key. Validate the chain and mint it accepts. Load once, then stay live. The history comes from one request, everything after that from the stream. After a relay restart or a dropped browser socket, load the history again to fill the gap. Snap times to your bars. Markers sit on bar times, so round created_at down to your candle interval and keep the marker list sorted. Only theses from your platform? Open the stream with scope=instance and call /v1/theses with scope=instance (csid.thesesStream({ scope: 'instance' }) and listTheses({ scope: 'instance' }) in the SDK). See Reach.

Reference

Token theses

How theses work, the widget and the API.

Theses stream

Frames, events and limits of the live stream.