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

# subscribeToEvents

Open a live WebSocket to the ZyFAI risk engine and get a callback the moment something changes: a stablecoin drifting off peg, a pool bleeding liquidity, or a new collateral type showing up in a vault. No wallet, no polling loop — just handlers.

<Tip title="No wallet required">
  Like `simulateBestPositions`, this only needs your API key. It's a good fit for dashboards, alerting, and monitoring that needs to run independently of any one user's session.
</Tip>

## Signature

```typescript theme={null}
subscribeToEvents(handlers: ZyfaiEventHandlers, filters?: ZyfaiEventFilters): () => void
```

## Parameters

| Parameter  | Type                 | Required | Description                                                                                                  |
| ---------- | -------------------- | :------: | ------------------------------------------------------------------------------------------------------------ |
| `handlers` | `ZyfaiEventHandlers` |     ✅    | Callbacks for each event type you care about.                                                                |
| `filters`  | `ZyfaiEventFilters`  |     ❌    | Narrow the stream to specific chains/protocols/pools. Omit a field to receive everything for that dimension. |

```typescript theme={null}
interface ZyfaiEventHandlers {
  onDepeg?: (data: DepegEvent) => void;
  onLiquidityDrop?: (data: LiquidityDropEvent) => void;
  onNewCollateralDetected?: (data: NewCollateralDetectedEvent) => void;
  onError?: (error: unknown) => void;
}

interface ZyfaiEventFilters {
  chains?: string[];
  protocols?: string[];
  pools?: string[];
}
```

## Returns

An `unsubscribe` function.

<Warning title="Always call the returned function">
  `subscribeToEvents` opens a real WebSocket connection. Call the function it returns as soon as you no longer need the stream — on component unmount, on page leave, whenever the caller goes away — or you'll leak the connection.
</Warning>

## Event types

### `onDepeg`

```typescript theme={null}
interface DepegEvent {
  token: string;
  price: number;
  deviation: number;              // percent off peg
  severity: "warning" | "critical";
  previousSeverity?: string;      // present when severity just changed
  affectedPools: { protocol: string; pool: string; chain: string }[];
  timestamp: string;
}
```

### `onLiquidityDrop`

```typescript theme={null}
interface LiquidityDropEvent {
  protocol: string;
  pool: string;
  chain: string;
  asset: string;
  previousLiquidityUsd: number;
  currentLiquidityUsd: number;
  dropPercent: number;
  windowMinutes: number;
  timestamp: string;
}
```

### `onNewCollateralDetected`

```typescript theme={null}
interface NewCollateralDetectedEvent {
  protocol: string;
  pool: string;
  chain: string;
  asset: string;
  exposureUsd: number;
  percentOfTvl: number;
  timestamp: string;
}
```

## Good to know

A few behaviors worth knowing before you build against this, confirmed by connecting to the live socket directly:

* **A quiet feed is a healthy feed.** A 25-second subscription with real filters produced zero events — that's expected, not broken. Real depegs and liquidity crunches aren't hourly occurrences, so don't design your UI around "an event should have arrived by now."
* **It reconnects on its own.** Treat `onError` as *"reconnecting…"*, not *"the stream is dead."* Don't tear your UI down on the first error.
* **Don't rely on `onError` to validate your API key.** Subscribing with a deliberately invalid key produced no error within 20 seconds in testing. If you need to confirm a key works, check it with a normal REST call (like `simulateBestPositions`) first — don't wait on this socket to tell you.
* All three `filters` fields are independent and optional — set only the ones you need.

## Examples

### Simplest subscription

```typescript theme={null}
const unsubscribe = sdk.subscribeToEvents({
  onDepeg: (e) => console.log(`${e.token} depeg — ${e.deviation}% (${e.severity})`),
  onLiquidityDrop: (e) => console.log(`${e.pool} liquidity -${e.dropPercent}%`),
  onNewCollateralDetected: (e) => console.log(`New collateral: ${e.asset} in ${e.pool}`),
  onError: (err) => console.error("stream error", err),
});

// later
unsubscribe();
```

### Filtered to specific chains/protocols/pools

```typescript theme={null}
const unsubscribe = sdk.subscribeToEvents(
  { onDepeg: (e) => alertMyTeam(e) },
  {
    chains: ["Ethereum", "Base"],
    protocols: ["morpho"],
    pools: ["gauntlet usdc core"],
  },
);
```

### Cleaning up in React

```tsx theme={null}
useEffect(() => {
  const unsubscribe = sdk.subscribeToEvents({ onDepeg: handleDepeg });
  return unsubscribe; // runs on unmount
}, []);
```
