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

# WebSocket

> Upgrade to a WebSocket that carries any number of live channels (up to 200 per socket).
Send JSON ops, receive JSON frames:

```
→ {"op":"subscribe","id":"t1","channel":"trades","chain":"sol","token":"<mint>"}
← {"type":"subscribed","id":"t1","channel":"trades"}
← {"id":"t1","channel":"trades","chain":"sol","token":"<mint>","type":"snapshot","data":[Trade…]}
← {"id":"t1","channel":"trades","chain":"sol","token":"<mint>","type":"trade","data":Trade}
→ {"op":"unsubscribe","id":"t1"}
→ {"op":"ping"}   ← {"type":"pong"}
```

Query parameters of the upgrade URL (`?channel=trades&chain=sol&token=…`) subscribe one
channel right away. Channels and frames: see the Streaming guide. While the server is at
capacity, a new socket's upgrade answers `503` (`server_busy`, `Retry-After: 30`); open
sockets keep running. The same socket is at `wss://ws.raze.bot` (the bare path is
`/v1/ws`).

**A Solana block that loses its fork.** Its trades may already have gone out live, and they
never happened there. On Solana the `trades` channel can then send one `retract` frame per
lost slot, after the trades it names, usually 10–40 s after them:

```
← {"id":"t1","channel":"trades","chain":"sol","token":"<mint>","type":"retract",
   "data":[{"signature":"<sig>","wallet":"<wallet>","slot":452995200,"reason":"abandoned"}]}
```

Remove the rows it lists, by `signature` + `wallet` (every row of that pair). A transaction
that landed in another block comes again later as a new `trade`, with the same signature and
that block's amounts and time. Never handle a frame type you do not know as a trade. On
`candles` the same event can bring a fresh `snapshot`, its candles built again without the
lost slot; `token`, `launchpad` and `wallet` send nothing new for it.


One socket, up to 200 channels. Protocol, frames and examples: [WebSocket guide](/streaming/websocket). Channels and their frames: [Channels](/streaming/channels).


## OpenAPI

````yaml GET /v1/ws
openapi: 3.1.0
info:
  title: Raze Market Data API
  version: 1.0.0
  description: >
    Multichain market data for tokens, trades, charts, holders, launchpads and
    wallets on

    Solana, Ethereum, BNB Chain, Base and Robinhood Chain, as REST snapshots and
    live streams.


    **Conventions, everywhere:**

    - Chains: `sol`, `eth`, `bsc`, `base`, `robinhood` (aliases `solana`,
    `ethereum`, `bnb`, `hood` and network ids work too).

    - EVM addresses are answered lowercase; Solana addresses are case-sensitive.

    - Amounts in USD end in `Usd`; percents are 0–100 and end in `Percent`;
    times are Unix **milliseconds**.

    - A value nobody knows is `null`, never `0`.

    - Success: `{"data": …}`, plus `"next"` on paged lists (pass it back as
    `cursor`, as given). A
      page can hold fewer rows than `limit`, even none, and still carry `next`: a list ends only
      where `next` is `null`.
    - Failure: `{"error": {"code", "message"}}` with status 400 (`bad_request`),
    401 (`unauthorized`),
      404 (`not_found`), 429 (`rate_limited`), 502 (`upstream_unavailable`), or 503 with a
      `Retry-After` header (`upstream_unavailable` on a page to ask for again, `server_busy` on a
      new live connection).
    - A Solana address that does not decode to a 32-byte key is a 400 wherever
    one token or wallet
      is named. Lists (`/v1/tokens?ids=`, `/v1/prices?tokens=`) leave out an id that looks like a
      Solana address (32 to 44 base58 characters) but is not a 32-byte key; an id that does not look
      like an address still fails the whole list with 400.

    **Auth:** send your key as `x-api-key`, `Authorization: Bearer <key>`, or
    `?apiKey=` (for

    WebSocket and EventSource, which cannot set headers). `/health` and
    `/v1/openapi.yaml` need no

    key.


    **Live:** one WebSocket at `/v1/ws` carries any number of channels (also at

    `wss://ws.raze.bot`); the same channels are available one per connection as
    Server-Sent Events

    at `/v1/stream/{channel}`. Every channel sends a `snapshot` frame first,
    then changes.
servers:
  - url: https://api.raze.bot
    description: Production
security:
  - ApiKeyHeader: []
  - Bearer: []
  - ApiKeyQuery: []
tags:
  - name: catalog
    description: Health, chains and token search
  - name: tokens
    description: Token snapshot, trades, candles, holders, top traders, image
  - name: discovery
    description: Trending, screener and launchpad boards
  - name: wallets
    description: Wallet leaderboard, stats, holdings, PnL and swaps
  - name: prices
    description: Native coin prices and token prices
  - name: live
    description: WebSocket and Server-Sent Events
paths:
  /v1/ws:
    get:
      tags:
        - live
      summary: WebSocket
      description: >
        Upgrade to a WebSocket that carries any number of live channels (up to
        200 per socket).

        Send JSON ops, receive JSON frames:


        ```

        →
        {"op":"subscribe","id":"t1","channel":"trades","chain":"sol","token":"<mint>"}

        ← {"type":"subscribed","id":"t1","channel":"trades"}

        ←
        {"id":"t1","channel":"trades","chain":"sol","token":"<mint>","type":"snapshot","data":[Trade…]}

        ←
        {"id":"t1","channel":"trades","chain":"sol","token":"<mint>","type":"trade","data":Trade}

        → {"op":"unsubscribe","id":"t1"}

        → {"op":"ping"}   ← {"type":"pong"}

        ```


        Query parameters of the upgrade URL
        (`?channel=trades&chain=sol&token=…`) subscribe one

        channel right away. Channels and frames: see the Streaming guide. While
        the server is at

        capacity, a new socket's upgrade answers `503` (`server_busy`,
        `Retry-After: 30`); open

        sockets keep running. The same socket is at `wss://ws.raze.bot` (the
        bare path is

        `/v1/ws`).


        **A Solana block that loses its fork.** Its trades may already have gone
        out live, and they

        never happened there. On Solana the `trades` channel can then send one
        `retract` frame per

        lost slot, after the trades it names, usually 10–40 s after them:


        ```

        ←
        {"id":"t1","channel":"trades","chain":"sol","token":"<mint>","type":"retract",
           "data":[{"signature":"<sig>","wallet":"<wallet>","slot":452995200,"reason":"abandoned"}]}
        ```


        Remove the rows it lists, by `signature` + `wallet` (every row of that
        pair). A transaction

        that landed in another block comes again later as a new `trade`, with
        the same signature and

        that block's amounts and time. Never handle a frame type you do not know
        as a trade. On

        `candles` the same event can bring a fresh `snapshot`, its candles built
        again without the

        lost slot; `token`, `launchpad` and `wallet` send nothing new for it.
      operationId: openWebSocket
      parameters:
        - name: apiKey
          in: query
          description: The key, for clients that cannot set headers
          schema:
            type: string
        - name: channel
          in: query
          schema:
            type: string
            enum:
              - trades
              - candles
              - token
              - launchpad
              - prices
              - wallet
        - name: chain
          in: query
          schema:
            type: string
        - name: token
          in: query
          schema:
            type: string
        - name: interval
          in: query
          schema:
            type: string
        - name: unit
          in: query
          schema:
            type: string
        - name: board
          in: query
          schema:
            type: string
        - name: wallet
          in: query
          schema:
            type: string
      responses:
        '101':
          description: Switching protocols
        '401':
          $ref: '#/components/responses/Unauthorized'
        '503':
          $ref: '#/components/responses/Busy'
components:
  responses:
    Unauthorized:
      description: Missing or unknown key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: unauthorized
              message: missing or unknown API key (send it as x-api-key)
    Busy:
      description: >-
        The server is at capacity and refuses new live connections; open ones
        keep running. Connect again after `Retry-After` seconds
      headers:
        Retry-After:
          schema:
            type: integer
            example: 30
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: server_busy
              message: the server is at capacity, retry in 30 s
  schemas:
    Error:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              enum:
                - bad_request
                - unauthorized
                - not_found
                - rate_limited
                - upstream_unavailable
                - server_busy
            message:
              type: string
  securitySchemes:
    ApiKeyHeader:
      type: apiKey
      in: header
      name: x-api-key
    Bearer:
      type: http
      scheme: bearer
    ApiKeyQuery:
      type: apiKey
      in: query
      name: apiKey

````

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