Skip to main content

Stream Quotes

The Vulcx quote stream pushes a fresh quote whenever the price of a token pair changes, so your UI can show a live rate without polling. It’s a WebSocket endpoint that speaks plain JSON.
Stream vs. poll. Use streaming for a continuously updating price (a swap form, a price ticker). For a single quote — for example, right before building a transaction — use GET /api/v1/quote. The streamed amountOut matches what /quote returns for the same pair and amount. For the full message schema, see the Stream Quotes API reference.
Unlike the REST endpoints (/quote, /swap, /instructions, /price), which accept an optional key, the stream always requires one. Browsers can’t set custom headers on a WebSocket handshake, so the key goes in the URL as ?key= — see Authentication.

How it works

  1. Open a WebSocket connection.
  2. Send a subscribe message listing the pairs you care about.
  3. Receive an immediate first quote for each pair, then a subscribed ack.
  4. Receive a new quote message whenever that pair’s price materially changes.
  5. Send unsubscribe to stop a stream, or close the socket to end them all.

Subscribe

Each pair is { in, out, amount, exactIn }:
string
required
Input token mint address (base58-encoded public key).
string
required
Output token mint address (base58-encoded public key).
string
required
Amount in smallest token units, as a string. For FOGO (9 decimals): 1000000000 = 1 FOGO.
boolean
required
true quotes amount as the exact input (ExactIn); false treats it as the exact desired output (ExactOut).

Handle messages

Three server message types arrive on the socket:
  • quote — a live quote: { type, in, out, amount, amountOut, priceImpactBps, hops, slot, quoteId, validForMs, firmForMs }. The quoteId is a firm-quote commitment: pass it to POST /swap to execute at exactly the streamed price.
  • invalidate{ type, quoteId }: the last quote pushed for a pair drifted past the firm margin, so stop offering that quoteId as a firm price (a fresh quote follows).
  • subscribed / unsubscribed / error — acks. Errors include a message; subscribe/unsubscribe acks include a count of accepted pairs.
A quote is only re-sent when amountOut, priceImpactBps, or hops changes — so every message you receive is a genuine price update.

Examples

Unsubscribe

Send the same pair with op: "unsubscribe" to stop receiving updates for it:
Closing the socket cancels all of a connection’s subscriptions.

Route templates for CPI integrators

The same socket also streams CPI route templates — the full POST /cpi/route-accounts payload (route instruction, accounts, LUTs), pushed only when the template actually changes. Liquidation keepers hold the latest template in memory and fire with zero HTTP round-trips:
See On-Chain Swaps (CPI) → Streaming route templates for semantics (seq, change-only pushes, corridor constraints). unsubscribe_route mirrors unsubscribe. Max 32 route subscriptions per connection.

Reconnection & limits

  • Reconnect on close. Subscriptions live with the connection. After an unexpected close, reopen the socket and re-send your subscribe messages.
  • Read promptly. A connection whose outbound queue overflows (a slow reader) is dropped rather than buffered. If this happens, reconnect and resubscribe.
  • Up to 256 subscriptions per connection (32 for subscribe_route). Spread more across multiple connections.
Last modified on August 31, 2026