SSE Price Stream
GET /v2/updates/price/stream
Subscribe to real-time price updates via Server-Sent Events (SSE). This is the primary way to get live execution prices.
Request
bash
curl -N "https://mainnet.proxy.ryze.pro/v2/updates/price/stream?ids[]=ff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace&ids[]=eaa020c61cc479712813461ce153894a96a6c00b21ed0cfc2798d1f9a9e9c94a"Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
ids[] | string | Yes | Pyth hex feed ID (repeatable for multiple feeds) |
Response
The response is an SSE stream (text/event-stream). Each event contains a JSON payload:
data: {"parsed":[{"id":"ff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace","price":{"price":"160025000000","conf":"0","expo":-8,"publish_time":1713200000},"ema_price":{"price":"160025000000","conf":"0","expo":-8,"publish_time":1713200000},"blend":{"token":"0x4200000000000000000000000000000000000006","pythPrice":"1600250000000000000000","cexPrice":"1600300000000000000000","blendFactor":"500000000000000000","blendedPrice":"1600275000000000000000"}}]}Behavior
- Initial snapshot: Immediately sends cached prices for all requested feeds
- Live updates: Sends new prices as they arrive (~200ms cadence from Pyth Pro)
- Heartbeat: Comment lines (
: keepalive) every 15 seconds to keep the connection alive - Filtering: Only sends updates for the feed IDs you subscribed to
JavaScript Example
javascript
const feedIds = [
'ff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace', // ETH
'eaa020c61cc479712813461ce153894a96a6c00b21ed0cfc2798d1f9a9e9c94a', // USDC
'2817d7bfe5c64b8ebd8cb2cb5f4f59c640453faa953a0f2f8067e0e83f4db8c9', // cbBTC
];
const params = feedIds.map(id => `ids[]=${id}`).join('&');
const url = `https://mainnet.proxy.ryze.pro/v2/updates/price/stream?${params}`;
const eventSource = new EventSource(url);
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
for (const update of data.parsed) {
const price = Number(update.price.price) * Math.pow(10, update.price.expo);
console.log(`${update.id.slice(0, 8)}...: $${price.toFixed(2)}`);
// If blending is active, the execution price is in blend.blendedPrice (WAD)
if (update.blend) {
const execPrice = Number(BigInt(update.blend.blendedPrice)) / 1e18;
console.log(` Execution price: $${execPrice.toFixed(2)}`);
}
}
};
eventSource.onerror = (err) => {
console.error('SSE error, will auto-reconnect:', err);
};React Example
tsx
import { useEffect, useRef, useState } from 'react';
function usePriceStream(feedIds: string[]) {
const [prices, setPrices] = useState<Record<string, number>>({});
const esRef = useRef<EventSource | null>(null);
useEffect(() => {
const params = feedIds.map(id => `ids[]=${id}`).join('&');
const es = new EventSource(
`https://mainnet.proxy.ryze.pro/v2/updates/price/stream?${params}`
);
es.onmessage = (event) => {
const data = JSON.parse(event.data);
setPrices(prev => {
const next = { ...prev };
for (const update of data.parsed) {
next[update.id] = Number(update.price.price) * Math.pow(10, update.price.expo);
}
return next;
});
};
esRef.current = es;
return () => es.close();
}, [feedIds.join(',')]);
return prices;
}Response Headers
| Header | Value |
|---|---|
Content-Type | text/event-stream |
Cache-Control | no-cache, no-transform |
Connection | keep-alive |
Access-Control-Allow-Origin | * |
Notes
- The stream sends padding comments on initial connection to flush through reverse proxies (Cloudflare)
- If a client falls behind, updates are dropped (non-blocking) to prevent backpressure
- The
EventSourceAPI auto-reconnects on network errors - Updates arrive at ~500ms broadcast cadence (coalesced from ~200ms Pyth Pro updates)