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

# SVM Price Subscriptions

> Subscribe to real-time Solana token price updates over the WebSocket connection.

Subscribe to real-time price updates for Solana tokens. When a subscribed token's price changes, you receive a `priceUpdate` event on your Socket.IO connection with the latest price from the highest-liquidity pool.

> **Live updates are Socket.IO only.** You can manage subscriptions (subscribe, unsubscribe, list active) over either transport, but `priceUpdate` and `subscriptionExpiring` events are pushed only over a Socket.IO connection. Over HTTP, the subscribe/unsubscribe/active endpoints just register and query subscriptions; they do not deliver price updates. To receive live prices you must be connected via Socket.IO.

***

## Subscription Limits

Maximum active subscriptions per tier:

| Tier       | Max Subscriptions |
| ---------- | ----------------- |
| Free       | 0                 |
| Basic      | 10                |
| Premium    | 100               |
| Enterprise | 1,000             |

***

## Subscribe

Subscribe to price updates for one or more tokens.

**Endpoint:** `/svm/price/subscribe`

| Parameter | Type      | Required | Description                                                                            |
| --------- | --------- | -------- | -------------------------------------------------------------------------------------- |
| `chain`   | string    | Yes      | Always `sol`                                                                           |
| `tokens`  | string\[] | Yes      | Array of token mint addresses (min 1)                                                  |
| `ttlMs`   | number    | No       | Subscription duration in milliseconds. Max: 604,800,000 (7d), default: 21,600,000 (6h) |

**Example:**

<Tabs>
  <Tab title="Socket.IO">
    ```typescript theme={null}
    socket.emit("/svm/price/subscribe", {
      chain: "sol",
      tokens: [
        "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
        "So11111111111111111111111111111111111111112",
      ],
      ttlMs: 21600000, // 6 hours
    });
    ```
  </Tab>

  <Tab title="HTTP">
    ```typescript theme={null}
    await fetch("https://api.chainworks.co/svm/price/subscribe", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: CHAINWORKS_API_AUTH_TOKEN,
      },
      body: JSON.stringify({
        chain: "sol",
        tokens: [
          "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
          "So11111111111111111111111111111111111111112",
        ],
        ttlMs: 21600000, // 6 hours
      }),
    });
    ```
  </Tab>
</Tabs>

**Response:**

```json theme={null}
{
  "success": true,
  "result": {
    "subscribed": [
      "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
      "So11111111111111111111111111111111111111112"
    ]
  }
}
```

Re-subscribing to an already-subscribed token refreshes its TTL without counting against the subscription limit.

***

## Unsubscribe

Unsubscribe from price updates for one or more tokens.

**Endpoint:** `/svm/price/unsubscribe`

| Parameter | Type      | Required | Description                                  |
| --------- | --------- | -------- | -------------------------------------------- |
| `chain`   | string    | Yes      | Always `sol`                                 |
| `tokens`  | string\[] | Yes      | Array of token mint addresses to unsubscribe |

**Example:**

<Tabs>
  <Tab title="Socket.IO">
    ```typescript theme={null}
    socket.emit("/svm/price/unsubscribe", {
      chain: "sol",
      tokens: ["EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"],
    });
    ```
  </Tab>

  <Tab title="HTTP">
    ```typescript theme={null}
    await fetch("https://api.chainworks.co/svm/price/unsubscribe", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: CHAINWORKS_API_AUTH_TOKEN,
      },
      body: JSON.stringify({
        chain: "sol",
        tokens: ["EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"],
      }),
    });
    ```
  </Tab>
</Tabs>

**Response:**

```json theme={null}
{
  "success": true,
  "result": {
    "unsubscribed": ["EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"]
  }
}
```

***

## Active Subscriptions

List all active (non-expired) price subscriptions.

**Endpoint:** `/svm/price/active_subscriptions`

| Parameter | Type   | Required | Description  |
| --------- | ------ | -------- | ------------ |
| `chain`   | string | Yes      | Always `sol` |

**Example:**

<Tabs>
  <Tab title="Socket.IO">
    ```typescript theme={null}
    socket.emit("/svm/price/active_subscriptions", {
      chain: "sol",
    });
    ```
  </Tab>

  <Tab title="HTTP">
    ```typescript theme={null}
    await fetch("https://api.chainworks.co/svm/price/active_subscriptions", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: CHAINWORKS_API_AUTH_TOKEN,
      },
      body: JSON.stringify({
        chain: "sol",
      }),
    });
    ```
  </Tab>
</Tabs>

**Response:**

```json theme={null}
{
  "success": true,
  "result": {
    "tokens": [
      "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
      "So11111111111111111111111111111111111111112"
    ]
  }
}
```

***

## Price Update Event

When a subscribed token's price changes, you receive a `priceUpdate` event. Updates are sourced from the highest-liquidity pool for the token and deduplicated so you only receive meaningful price changes.

```typescript theme={null}
socket.on("priceUpdate", (data) => {
  console.log(data);
});
```

**Event payload:**

```json theme={null}
{
  "chain": "sol",
  "token": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
  "pool": {
    "type": "RaydiumV4",
    "lp": "58oQChx4yWmvKdwLLZzBi4ChoCc2fqCUWBkwMihLYQo2",
    "backingToken": "So11111111111111111111111111111111111111112",
    "rawPrice": 0.000034,
    "priceUsd": 0.0051,
    "tokenReserve": "1000000000000",
    "backingReserve": "34000000"
  },
  "slotNumber": 285000000,
  "timestamp": 1710979200
}
```

| Field                 | Type   | Description                                            |
| --------------------- | ------ | ------------------------------------------------------ |
| `chain`               | string | Always `sol`                                           |
| `token`               | string | Token mint address                                     |
| `pool.type`           | string | DEX type (e.g. `RaydiumV4`, `PumpSwap`, `MeteoraDLMM`) |
| `pool.lp`             | string | Liquidity pool address                                 |
| `pool.backingToken`   | string | Backing token mint (e.g. SOL or USDC)                  |
| `pool.rawPrice`       | number | Raw price ratio (token lamports / backing lamports)    |
| `pool.priceUsd`       | number | Price of 1 full token in USD                           |
| `pool.tokenReserve`   | string | Token reserve amount in the pool                       |
| `pool.backingReserve` | string | Backing token reserve amount in the pool               |
| `slotNumber`          | number | Solana slot number of the update                       |
| `timestamp`           | number | Unix timestamp in seconds                              |

***

## Subscription Expiring Event

You receive a `subscriptionExpiring` event shortly before a subscription expires, and again when it actually expires. Use this to re-subscribe if needed.

```typescript theme={null}
socket.on("subscriptionExpiring", (data) => {
  console.log(data);
});
```

**Event payload:**

```json theme={null}
{
  "chain": "sol",
  "token": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
  "expiresAt": 1711065600,
  "expired": false
}
```

| Field       | Type    | Description                                             |
| ----------- | ------- | ------------------------------------------------------- |
| `chain`     | string  | Always `sol`                                            |
| `token`     | string  | Token mint address                                      |
| `expiresAt` | number  | Unix timestamp (seconds) when the subscription expires  |
| `expired`   | boolean | `false` when expiring soon, `true` when already expired |
