> ## Documentation Index
> Fetch the complete documentation index at: https://finance.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Stream Live Prices

> Streams live bids, trades, and last prices for prediction-market contracts as server-sent events.

**Use Case:** Show a contract's latest YES and NO prices and update them as orders and trades arrive, without polling.


<Note>
  **What this stream gives you.** Open one HTTP connection and the server keeps it open, pushing each contract's latest price, every new bid, and every trade as they happen. It uses [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events): a browser reads it with `EventSource`, and any HTTP client can read it line by line.
</Note>

## Request

```text theme={null}
GET /v1/predictions/stream?symbols=HORC_1126_Democratic,HORC_1126_Republican
GET /v1/predictions/stream?events=HORC_1126
```

| Parameter | Description |
| - | - |
| `symbols` | Contract symbols, comma-separated or repeated (`symbols=A&symbols=B`). |
| `events` | Event IDs, comma-separated or repeated. Streams every `ACTIVE` contract under each event. |

Send `symbols`, `events`, or both; duplicates are removed. A connection can carry up to **200** contracts, counted after events are expanded.

Event IDs come from [Search](/api-reference/predictions/search) with `type=events`, or from a contract's `eventId`. [Get Event Contracts](/api-reference/predictions/get-event-contracts) lists the contracts an event expands to. An event is expanded once, when you connect: a contract listed under it later is not added until you reconnect.

## Events

ForecastEx takes **buy orders only**. Every order is a bid, for YES or for NO, so there is no ask.

| Event | When | Payload |
| - | - | - |
| `subscribed` | First, once | Every contract on the stream, and each requested event's contracts |
| `snapshot` | Once per contract, before anything else for it | Each outcome's last trade, and the contract's statistics |
| `bid` | Each new YES or NO bid | The order as the venue received it |
| `trade` | Each trade | One leg of a match |
| `stats` | Whenever the contract's statistics change | The `contract` block alone |
| `gap` | When you fell too far behind | The contract whose bids or trades you missed. A fresh `snapshot` follows. |

A `: ping` comment is sent every 15 seconds to keep idle connections open.

### subscribed

```json theme={null}
{
  "symbols": ["HORC_1126_Democratic", "HORC_1126_Republican"],
  "events": { "HORC_1126": ["HORC_1126_Democratic", "HORC_1126_Republican"] }
}
```

`events` is present only when you asked for events.

### snapshot

```json theme={null}
{
  "symbol": "HORC_1126_Democratic",
  "yes": { "last": "0.50", "lastSize": "1" },
  "no":  { "last": "0.50", "lastSize": "1" },
  "contract": {
    "high": "0.63",
    "low": "0.47",
    "settlement": "0.37",
    "volume": "123",
    "notional": "69.69",
    "openInterest": "54886",
    "tradingSession": "OPEN"
  },
  "receivedAtUnixMs": 1791499255775
}
```

| Field | Notes |
| - | - |
| `yes`, `no` | Each outcome's last trade price and size. `null` for an outcome that has not traded. |
| `contract.volume` | Contracts matched in the session. One match is one contract, even though it prints as two trades. |
| `contract.notional` | Total value traded in the session. |
| `contract.openInterest` | Open contracts. |
| `contract.high`, `low`, `settlement` | Session high, low, and settlement price. |
| `contract.tradingSession` | The venue's state for the contract, such as `OPEN`, `HALTED`, or `CLOSED`. |

The venue reports a contract's last trade without saying which outcome it was for. The snapshot reads it as the YES price and sets NO to `1.00` minus it. After the first live trade, `yes` and `no` come from tagged trades.

### bid

```json theme={null}
{
  "symbol": "HORC_1126_Democratic",
  "outcome": "NO",
  "price": "0.62",
  "size": "1",
  "orderId": "CZ1P1MS4A1C1",
  "placedAtUnixNs": 1791499265208000000,
  "receivedAtUnixMs": 1791499265211
}
```

A bid is sent when it is placed. Its later fills and cancellation are not sent, so a `bid` event does not mean the order is still resting.

### trade

```json theme={null}
{
  "symbol": "HORC_1126_Democratic",
  "outcome": "NO",
  "price": "0.53",
  "size": "1",
  "tradeId": "CZKNTJJXE1DD",
  "aggressorSide": "Buy",
  "tradeTimeUnixNs": 1791499265208000000,
  "receivedAtUnixMs": 1791499265211
}
```

A match is a YES buyer and a NO buyer, so every match arrives as **two** `trade` events with the same `tradeId`: one for each outcome, at prices that add up to `1.00`. Count matches by `tradeId`, not by event.

### stats

```json theme={null}
{
  "symbol": "HORC_1126_Democratic",
  "contract": {
    "high": "0.63",
    "low": "0.47",
    "settlement": "0.37",
    "volume": "124",
    "notional": "70.16",
    "openInterest": "54887",
    "tradingSession": "OPEN"
  }
}
```

Each `stats` replaces the last. A match usually sends two: volume and notional change with the trade, and open interest follows. A new last price on its own sends no `stats`, because the `trade` events already carry it.

### Contracts from events

For a contract you subscribed to through `events`, every `snapshot`, `bid`, `trade`, `stats`, and `gap` also carries `eventId`:

```json theme={null}
{ "symbol": "HORC_1126_Democratic", "eventId": "HORC_1126", "outcome": "NO", "price": "0.62", "size": "1" }
```

## Ordering

* For each contract, `snapshot` comes first, and nothing else is sent for that contract before it.
* After that, `bid`, `trade`, and `stats` arrive in the order the venue sent them, and a match's two trades come before the `stats` they moved.
* Events for different contracts interleave.

If the contract is already being streamed, its snapshot is sent at once. Otherwise it arrives once the venue answers, usually within about a second.

## Reconnecting

Events have no IDs and are not replayed. When you reconnect, as `EventSource` does on its own, you receive a new `subscribed` and a fresh `snapshot` for every contract. Bids and trades sent while you were disconnected are lost, but the snapshot's prices and statistics show where the market is now.

## Examples

```bash cURL theme={null}
curl -N "https://api.aries.com/v1/predictions/stream?events=HORC_1126"
```

```javascript Browser theme={null}
const stream = new EventSource(
  "https://api.aries.com/v1/predictions/stream?symbols=HORC_1126_Democratic"
);

stream.addEventListener("snapshot", (e) => {
  const { symbol, yes, no, contract } = JSON.parse(e.data);
  console.log(symbol, "YES", yes.last, "NO", no.last, "volume", contract.volume);
});

stream.addEventListener("trade", (e) => {
  const { symbol, outcome, price, size } = JSON.parse(e.data);
  console.log(symbol, outcome, "traded", size, "@", price);
});

stream.addEventListener("bid", (e) => {
  const { symbol, outcome, price, size } = JSON.parse(e.data);
  console.log(symbol, "new", outcome, "bid", size, "@", price);
});
```

## Working with the stream

* **Prices are decimal strings.** `"0.53"`, not `0.53`. Parse them with a decimal type.
* **A missing value is `null`, not zero.** A `null` last price means the outcome has not traded.
* **Do not put the stream behind a buffering proxy.** Events must reach you as they are sent.

## Errors

Errors are returned before the stream opens, in the usual [error envelope](/prediction-api/overview#response-envelope):

| Status | `code` | When |
| - | - | - |
| `400` | `MISSING_SYMBOLS` | Neither `symbols` nor `events` names anything |
| `400` | `TOO_MANY_SYMBOLS` | More than 200 contracts after events are expanded |
| `400` | `INVALID_SYMBOL` | A symbol containing whitespace, `*`, or `>`, or with a leading or trailing dot |
| `400` | `UNKNOWN_EVENT` | An event ID that does not exist |
| `400` | `NO_LIVE_CONTRACTS` | An event with no `ACTIVE` contract |
| `503` | `SHUTTING_DOWN` | The server is restarting; reconnect |

An unknown **symbol** is not an error. It never receives a snapshot.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.