Realtime stream
Connect to /v1/stream, subscribe to what you show, re-read what changed.
What is live today
TREND runs on its own dev validator. The mainnet programs are not deployed: their ids are reserved and no launch exists there. Statement as of 2026-10-10.
wss://api.dev.trend.fun/v1/streamThe stream rides the API host. What crosses the socket is an announcement that something changed, not the changed
state. Re-read the REST route you already trust. A missed message costs one stale interval and a duplicate costs one
extra fetch; both are recoverable, where state assembled from a partly delivered stream is not. The one exception is the
cards frame, below.
Connect
On connect the server sends:
{ "kind": "hello", "at": 1789526549000, "v": 1 }Before your first valid sub frame, a socket is in broadcast scope on some deployments (it receives every event) and
in scoped scope on others (it receives only the global frames). Do not depend on either: always send a sub. The
first valid sub makes the socket scoped, and from then on it receives what it subscribed to plus the global frames.
Subscribe
Frames you send are JSON. v is optional and must be 1 when present.
| Frame | Effect |
|---|---|
{ "op": "sub", "tier": "cards", "mints": [ ... ] } | The card tier: the aggregated cards bundle filtered to those launches, plus their status and migration events. At most 100 per socket. It does not receive raw trade events. |
{ "op": "sub", "tier": "live", "mint": "<address>" } | The live tier: every trade, status and migration for one launch. A second sub for live replaces the first. |
{ "op": "sub", "topic": "launches" } | A named topic. launches announces new launches with their first card data inline. trades delivers every trade on the chain. At most 8 topics. |
{ "op": "unsub", ... } | The same three forms, to leave. unsub for cards without mints clears the set. |
mint and mints hold launch addresses. A malformed address is dropped from the frame, not a reason to close the
socket. A frame over 64 KB is ignored. When a sub names more than the cap allows, the surplus is trimmed and the
server answers { "kind": "suback", "accepted": n, "rejected": n, "cap": n }.
Frames you receive
kind | Meaning | What to do |
|---|---|---|
hello | Connected. | Nothing. |
ping | Heartbeat, every 25 seconds. | Nothing. Silence for longer is a dead connection: reconnect. |
cards | The home grid bundle. | It carries its own data. See below. |
trade | A trade landed on launch. | Fold it into your chart and feed, or re-read the trades. |
status, migration | A launch changed state. | Re-read GET /v1/launches/{id}. |
launch | A new launch (topic launches). | The first card data is in data. |
prices | Component prices were sampled. | Re-read GET /v1/assets. |
blockhash | A shared fresh blockhash, about once a second. | Optional. |
collectible | A collectible changed stage. | Re-read GET /v1/collectibles/{id}. |
resync | The server missed events from its bus (reason: "bus"). | Re-read the snapshot and what is on screen. The socket stays open. |
suback | A sub was trimmed. | Log it. |
Frames are JSON objects with a kind, an optional launch and optional data. data is free-form detail for a user
interface and never the authoritative state. A client that does not know a kind ignores it.
The one frame that carries data: cards
On the first sub for cards you receive a snapshot (full: true), then deltas that carry only what changed, each
with a monotonic seq and the prev it continues from. If a delta does not continue from the seq you hold, you have
provably missed one and cannot know what was in it: re-read the snapshot by subscribing again. Without that check a
lost delta is invisible and a card stays wrong.
Limits
Connections are capped per server and per address (24 anonymous connections per address by default). A refusal closes
with code 1013, "try again later": back off before you reconnect. An idle connection is closed with 1001. A client
that sends too many frames in a window is closed with 1008. A rolling deploy closes sockets with 1001 "server
shutting down": reconnect and subscribe again, because subscription state lives on the socket and does not follow you.
A client that survives
- Connect, wait for
hello, send yoursubframes. - On any close, wait with a growing delay and reconnect. Subscribe again.
- On every reconnect and on every
resync, re-read the REST routes you show. - If no frame of any kind arrives for 60 seconds, close and reconnect.