> For the complete documentation index, see [llms.txt](https://nlf.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://nlf.gitbook.io/docs/websocket.md).

# New Listings Feed WebSocket

A membership key is required to access the endpoints. Get one at [t.me/NLF\_websocket\_bot](https://t.me/NLF_websocket_bot).

## Keys

Keys differ on latency, regions, enabled channels, and history backfill window.

<table><thead><tr><th width="140">Key</th><th width="70">Delay</th><th width="180">Regions</th><th>Channels</th><th width="120">History backfill</th></tr></thead><tbody><tr><td><strong>FREE</strong></td><td>3s</td><td>-</td><td><code>feed</code></td><td>None</td></tr><tr><td><strong>STARTER</strong></td><td>20ms</td><td>Seoul + Tokyo + New York</td><td><code>new-listings</code>, <code>delistings</code>, <code>announcements</code>, enhanced variants</td><td>30 days</td></tr><tr><td><strong>PRO</strong></td><td>0ms</td><td>Seoul + Tokyo + New York</td><td>Same as STARTER</td><td>1 year</td></tr></tbody></table>

## Endpoints

Base paths per region. Append the channel name to build the full URL. All endpoints use `wss://` for WebSocket and `https://` for the historical REST API at the same path.

The `/v1/announcements` endpoints emit raw announcement streams and are faster than parsed or enhanced endpoints.

<table><thead><tr><th width="260">Host</th><th width="140">Used by</th><th>Paths</th></tr></thead><tbody><tr><td><code>seoul.newlistings.pro</code></td><td>STARTER, PRO</td><td><code>/v1/announcements</code>, <code>/v1/new-listings</code>, <code>/v1/delistings</code></td></tr><tr><td><code>tokyo.newlistings.pro</code></td><td>STARTER, PRO</td><td><code>/v1/announcements</code>, <code>/v1/new-listings</code>, <code>/v1/delistings</code>, <code>/v1/new-listings-enhanced</code>, <code>/v1/delistings-enhanced</code></td></tr><tr><td><code>ny.newlistings.pro</code></td><td>STARTER, PRO</td><td><code>/v1/announcements</code>, <code>/v1/new-listings</code>, <code>/v1/delistings</code></td></tr><tr><td><code>ws.newlistings.pro</code></td><td>FREE</td><td><code>/v1/feed</code></td></tr></tbody></table>

## Authenticating

Send your key in the `Authorization` header when opening the WebSocket. A quick check with `wscat`:

```bash
wscat -H "authorization: Bearer YOUR_KEY" \
  -c wss://tokyo.newlistings.pro/v1/new-listings
```

On success the server sends a single JSON message before streaming events:

```json
{
  "type": "success",
  "message": "Connection established successfully. Streaming started.",
  "channel": "new-listings",
  "delay": "0ms",
  "instance": "Tokyo"
}
```

See [Code examples](#code-examples) below for a complete client.

### Connection lifecycle

* **Ping / pong**: the server sends a WebSocket ping every 30 seconds. Reply with a pong to keep the connection open. Most client libraries do this automatically.
* **Reconnect**: reconnect after an unexpected close using a sensible backoff (e.g. 1s, 2s, 5s, capped at 30s).
* **Missed events**: stream connections do not replay history after a reconnect. Use the historical REST API to backfill the gap (STARTER and PRO only).

### Errors

The server returns standard HTTP status codes on the upgrade request and closes the connection.

<table><thead><tr><th width="100">Status</th><th>Meaning</th></tr></thead><tbody><tr><td><code>401</code></td><td>Missing, malformed, expired, or unauthorized key.</td></tr><tr><td><code>429</code></td><td>Too many requests. Slow down and retry after a short wait.</td></tr><tr><td><code>503</code></td><td>Authentication is temporarily unavailable. Retry shortly.</td></tr></tbody></table>

{% hint style="warning" %}
Many failed authentication attempts from the same IP lead to a temporary ban. Make sure your key is valid and your reconnect loop has a sensible backoff before retrying.
{% endhint %}

## Code examples

Minimal clients with auto-reconnect. Replace the URL with the endpoint for your key tier and region.

{% tabs %}
{% tab title="Node.js" %}

```javascript
const WebSocket = require("ws");

const URL = "wss://tokyo.newlistings.pro/v1/new-listings";

function connect() {
  const ws = new WebSocket(URL, {
    headers: { authorization: "Bearer YOUR_KEY" },
  });

  ws.on("open", () => console.log("open"));
  ws.on("message", (data) => console.log(JSON.parse(data)));
  ws.on("error", (err) => console.error(err.message));
  ws.on("close", () => {
    console.log("closed, reconnecting in 1s");
    setTimeout(connect, 1000);
  });
}

connect();
```

{% endtab %}

{% tab title="Python" %}

```python
# pip install websocket-client
import json, time, websocket

URL = 'wss://tokyo.newlistings.pro/v1/new-listings'
HEADERS = ["authorization: Bearer YOUR_KEY"]

def on_message(ws, msg):
    print(json.loads(msg))

def on_error(ws, err):
    print(f"error: {err}")

def on_close(ws, code, reason):
    print("closed, reconnecting in 1s")
    time.sleep(1)
    connect()

def connect():
    websocket.WebSocketApp(
        URL, header=HEADERS,
        on_message=on_message,
        on_error=on_error,
        on_close=on_close,
    ).run_forever(ping_interval=30, ping_timeout=10)

connect()
```

{% endtab %}
{% endtabs %}

## Message schemas

Each channel emits JSON objects with a stable shape. The channel you connected to determines the payload type.

### Timestamp and delay fields

For `new-listings`, `announcements`, `delistings`, and enhanced detail channels, `time` and `time_iso` are set by WSS when it receives the upstream UDS frame. They are not the exchange publication time and they are not copied from the upstream producer's timestamp.

If the upstream producer intentionally waits before writing to UDS, that wait is already reflected because WSS receives the frame later. For delayed subscriber buckets, WSS restamps `time` and `time_iso` to the WSS UDS receive time plus the bucket delay. The `delay` string in the payload shows the subscriber payload delay applied by WSS.

### Listings and delistings

```json
{
  "id": 3638602138738688,
  "time": 1776661200556,
  "time_iso": "2026-04-20T05:00:00.556Z",
  "announcement": "$PIEVERSE listed on Upbit spot (KRW)",
  "original_title": "파이버스(PIEVERSE) 신규 거래지원 안내 (KRW, BTC, USDT 마켓)",
  "url": "https://upbit.com/service_center/notice?id=6154",
  "exchange": "upbit",
  "type": "spot",
  "detections": [
    {
      "ticker": "PIEVERSE"
    }
  ]
}
```

<table><thead><tr><th width="140">Field</th><th width="80">Type</th><th>Notes</th></tr></thead><tbody><tr><td><code>id</code></td><td>int</td><td>Unique event ID.</td></tr><tr><td><code>time</code></td><td>int</td><td>Event timestamp in milliseconds since epoch.</td></tr><tr><td><code>time_iso</code></td><td>string</td><td>Same timestamp as ISO 8601.</td></tr><tr><td><code>announcement</code></td><td>string</td><td>Clean human-readable summary.</td></tr><tr><td><code>original_title</code></td><td>string</td><td>Original exchange announcement title (when available).</td></tr><tr><td><code>url</code></td><td>string</td><td>Link to the source announcement.</td></tr><tr><td><code>exchange</code></td><td>string</td><td>Normalized exchange identifier. See <a href="#exchange-coverage">Exchange coverage</a>.</td></tr><tr><td><code>type</code></td><td>string</td><td>Product type on that exchange (<code>spot</code>, <code>futures</code>, <code>pre-market</code>, etc.). See <a href="#exchange-coverage">Exchange coverage</a>.</td></tr><tr><td><code>detections</code></td><td>array</td><td>Tickers detected in the announcement, each with contracts when known.</td></tr></tbody></table>

Each entry in `detections` has `ticker`, and if available `project_name` and a `contracts` array of `{chain, contract}` objects.

### Enhanced listings and delistings (beta)

{% hint style="info" %}
The enhanced endpoints (`new-listings-enhanced`, `delistings-enhanced`) are available on the Tokyo host only and are in **beta**. Matching reads the provider snapshot refreshed before the announcement. The event path does not wait for CoinGecko, DexScreener, or another liquidity HTTP request before emitting.
{% endhint %}

`new-listings-enhanced` and `delistings-enhanced` emit the same base payload with additional fields on each detection. When the contract is published directly in the exchange announcement, it appears in `contracts` and is considered authoritative. When it isn't, a `suggested_match` is attached with the project and contract our matcher inferred for that ticker.

```json
{
  "announcement": "$W listed on Robinhood spot",
  "url": "https://robinhood.com/us/en/crypto/W",
  "exchange": "robinhood",
  "type": "spot",
  "detections": [
    {
      "ticker": "W",
      "project_name": "Wormhole",
      "metrics": {
        "circulating_market_cap_usd": 104676283,
        "fdv_usd": 189019094,
        "volume_24h_usd": 22973492,
        "circulating_supply": 5537527353,
        "total_supply": 10000000000
      },
      "contracts": [
        {
          "chain": "solana",
          "contract": "85VBFQZC9TZkfaptBWjvUw7YbZjy52A6mjtPGjstQAmQ",
          "dex_pairs": [
            {
              "dex_id": "raydium",
              "pair": "w/sol",
              "pair_contract": "So1Pool1111111111111111111111111111111111111",
              "volume_24h_usd": 1842500,
              "liquidity_usd": 920441
            }
          ]
        }
      ]
    }
  ]
}
```

When the contract is not in the announcement, the matcher attaches a `suggested_match` describing its best guess for the ticker:

```json
{
  "ticker": "ZEREBRO",
  "contracts": [],
  "suggested_match": {
    "confidence": "high",
    "project_name": "Zerebro",
    "metrics": { "circulating_market_cap_usd": 8127684, "fdv_usd": 10017797 },
    "suggested_contracts": [
      {
        "chain": "solana",
        "contract": "8x5VqbHA8D7NkD52uNuS5nnt3PwA8pLD34ymskeSo2Wn",
        "dex_pairs": [
          {
            "dex_id": "raydium",
            "pair": "zerebro/sol",
            "pair_contract": "So1Pool2222222222222222222222222222222222222",
            "volume_24h_usd": 2184320,
            "liquidity_usd": 481207
          }
        ]
      },
      {
        "chain": "ethereum",
        "contract": "0xabcabcabcabcabcabcabcabcabcabcabcabcabca",
        "dex_pairs": [
          {
            "dex_id": "uniswap",
            "pair": "zerebro/weth",
            "pair_contract": "0xpoolabcabcabcabcabcabcabcabcabcabcabcabc",
            "volume_24h_usd": 4200000,
            "liquidity_usd": 650000
          }
        ]
      }
    ]
  }
}
```

A `suggested_match` is a suggestion from our multi-datapoint matching algorithm. The `confidence` field shows how strong the match looks according to the matcher.

Provider-derived `suggested_contracts` contains the verified project contract with the largest accepted provider-reported DEX pool reserve. A source-owned contract remains under root `contracts`; if another chain has deeper liquidity, the distinct winner also appears under `suggested_match.suggested_contracts`. This is trading-liquidity context, not a claim that the source exchange supports deposits on that chain, and the reserve is not an executable price-impact quote.

Confidence levels:

* `medium`
* `high`
* `very high`

`metrics`:

| Field                        | Notes                                |
| ---------------------------- | ------------------------------------ |
| `circulating_market_cap_usd` | Market cap using circulating supply. |
| `fdv_usd`                    | Fully diluted valuation.             |
| `volume_24h_usd`             | Trailing 24-hour trading volume.     |
| `circulating_supply`         | Circulating token supply.            |
| `total_supply`               | Total token supply.                  |

`suggested_match.suggested_contracts[]` fields:

| Field       | Notes                                                                                                                                                 |
| ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| `chain`     | Normalized chain label.                                                                                                                               |
| `contract`  | Contract address.                                                                                                                                     |
| `dex_pairs` | Per-pool volume and liquidity, when pair data is available. Volume and liquidity are only ever reported per pair; there are no contract-level totals. |

`contracts[].dex_pairs` (and `suggested_match.suggested_contracts[].dex_pairs`):

| Field            | Notes                                                                                  |
| ---------------- | -------------------------------------------------------------------------------------- |
| `dex_id`         | DEX identifier. See [common values](#dex_id-values).                                   |
| `pair`           | Lowercased `base/quote` symbol, with no surrounding spaces and no DEX fee-tier suffix. |
| `pair_contract`  | Pool contract address.                                                                 |
| `volume_24h_usd` | Trailing 24-hour pair volume.                                                          |
| `liquidity_usd`  | Current pool liquidity.                                                                |

USD values are rounded to whole numbers. Any field may be absent when the data is not available.

#### `dex_id` values

The `dex_id` string is passed through from the data provider. It is not an enumeration, and new DEXes may appear at any time. Commonly seen values by chain:

| Chain      | Common `dex_id` values                                                      |
| ---------- | --------------------------------------------------------------------------- |
| `solana`   | `pumpswap`, `meteora`, `raydium`                                            |
| `ethereum` | `uniswap`, `uniswap_v2`, `uniswap_v3`, `uniswap-v4-ethereum`                |
| `bsc`      | `pancakeswap`, `pancakeswap-v3-bsc`, `pancakeswap-infinity-clmm`, `uniswap` |
| `base`     | `uniswap`, `aerodrome-base`, `aerodrome-slipstream-2`                       |

### Announcements

The `announcements` channel emits the raw stream of exchange announcements and is the fastest source for raw exchange signals. No ticker detection is performed.

```json
{
  "id": 1765546215726,
  "time": 1761719456916,
  "time_iso": "2026-04-20T06:30:56.916Z",
  "exchange": "kucoin",
  "announcement": "Funding Rate Settlement Frequency of Multiple USDⓈ-M Perpetual Contracts Will Be Resumed",
  "url": "https://www.kucoin.com/announcement/en-funding-rate-settlement-frequency-of-multiple-usd-m-perpetual-contracts-will-be-resumed"
}
```

### Feed

The `feed` channel is a compact stream. Listings from both source groups are included; `tier` identifies the group. Delistings remain primary-only.

```json
{
  "message": "$MEGA listed on Upbit spot (KRW)",
  "url": "https://upbit.com/service_center/notice?id=6184",
  "type": "listing",
  "tier": "primary"
}
```

<table><thead><tr><th width="140">Field</th><th width="80">Type</th><th>Notes</th></tr></thead><tbody><tr><td><code>message</code></td><td>string</td><td>Clean human-readable listing or delisting text.</td></tr><tr><td><code>url</code></td><td>string</td><td>Link to the source announcement.</td></tr><tr><td><code>type</code></td><td>string</td><td>Event type: <code>listing</code> for a new listing or <code>delisting</code> for a removal.</td></tr><tr><td><code>tier</code></td><td>string</td><td>Source group: <code>primary</code> for core sources or <code>secondary</code> for additional sources.</td></tr></tbody></table>

## Exchange coverage

Coverage is identical on the standard and enhanced variants of each channel. The `exchange` and `type` fields take values from the tables below.

{% tabs %}
{% tab title="Listings" %}

| Exchange                | Types                                                                                                       |
| ----------------------- | ----------------------------------------------------------------------------------------------------------- |
| `asterdex`              | `spot`, `futures`                                                                                           |
| `aevo`                  | `pre-market`                                                                                                |
| `binance`               | `spot`, `futures`, `alpha`, `launchpool`, `hodler_airdrop`, `megadrop`, `pre-market`                        |
| `bingx`                 | `spot`, `futures`, `pre-market`                                                                             |
| `bitget`                | `spot`, `futures`, `pre-market`                                                                             |
| `bithumb`               | `spot`                                                                                                      |
| `bitmart`               | `spot`, `futures`, `launchprime`, `pre-market`                                                              |
| `bybit`                 | `spot`, `futures`, `alpha`, `launchpad`, `launchpool`, `web3ido`, `pre-market`, `soon-spot`, `soon-futures` |
| `coinbase`              | `spot`, `roadmap`                                                                                           |
| `coinbaseinternational` | `futures`                                                                                                   |
| `coinex`                | `spot`, `futures`                                                                                           |
| `coinone`               | `spot`                                                                                                      |
| `cryptocom`             | `spot`                                                                                                      |
| `gate`                  | `spot`, `futures`, `alpha`, `pre-market`                                                                    |
| `htx`                   | `spot`, `futures`                                                                                           |
| `hyperliquid`           | `spot`, `futures`, `pre-market`                                                                             |
| `korbit`                | `spot`                                                                                                      |
| `kraken`                | `spot`, `soon-spot`                                                                                         |
| `kucoin`                | `spot`, `futures`, `alpha`                                                                                  |
| `lighter`               | `pre-market`                                                                                                |
| `mexc`                  | `spot`, `futures`, `launchpool`, `pre-market`                                                               |
| `okx`                   | `spot`, `futures`, `pre-market`, `jumpstart`                                                                |
| `robinhood`             | `spot`                                                                                                      |
| `upbit`                 | `spot`                                                                                                      |
| {% endtab %}            |                                                                                                             |

{% tab title="Delistings" %}

| Exchange     | Types                      |
| ------------ | -------------------------- |
| `asterdex`   | `futures`                  |
| `binance`    | `spot`, `futures`, `alpha` |
| `bingx`      | `spot`, `futures`          |
| `bitget`     | `spot`, `futures`          |
| `bithumb`    | `spot`                     |
| `bitmart`    | `spot`                     |
| `bybit`      | `spot`, `futures`, `alpha` |
| `coinbase`   | `spot`, `futures`          |
| `coinex`     | `spot`                     |
| `coinone`    | `spot`                     |
| `gate`       | `spot`, `futures`          |
| `htx`        | `spot`, `futures`          |
| `korbit`     | `spot`                     |
| `kucoin`     | `spot`, `futures`          |
| `mexc`       | `spot`, `futures`          |
| `okx`        | `spot`, `futures`          |
| `upbit`      | `spot`, `caution-spot`     |
| {% endtab %} |                            |

{% tab title="Announcements" %}
Includes every exchange that appears in listings or delistings, plus announcement-only sources that don't parse into listing events:

`binance`, `bingx`, `bitget`, `bithumb`, `bitmart`, `bullish`, `bybit`, `coinbase`, `coinbaseinternational`, `coinex`, `coinlist`, `coinone`, `cryptocom`, `gate`, `gemini`, `htx`, `hyperliquid`, `korbit`, `kraken`, `kucoin`, `mexc`, `okx`, `robinhood`, `upbit`
{% endtab %}

{% tab title="Chains" %}
The `chain` field on contract entries takes one of:

`arbitrum`, `avalanche`, `base`, `bsc`, `ethereum`, `katana`, `linea`, `optimism`, `polygon`, `solana`, `sonic`, `sui`, `tron`

Additional chain names may appear when an exchange announcement references a network not in the list above. Values are always lowercase.
{% endtab %}
{% endtabs %}

## Historical data

STARTER and PRO keys can backfill recent events with a `GET` request at the same path as the WebSocket. Authenticate with the same `Authorization: Bearer` header.

```bash
curl -H "authorization: Bearer YOUR_KEY" \
  "https://tokyo.newlistings.pro/v1/new-listings?limit=50"
```

### Query parameters

| Parameter  | Type   | Notes                                                                                        |
| ---------- | ------ | -------------------------------------------------------------------------------------------- |
| `before`   | int    | Exclusive upper bound in milliseconds since epoch.                                           |
| `after`    | int    | Inclusive lower bound in milliseconds since epoch.                                           |
| `limit`    | int    | Maximum events to return. Defaults to `50`, capped at `100`.                                 |
| `exchange` | string | Filter by exchange. Use one of the values from [Exchange coverage](#exchange-coverage).      |
| `cursor`   | string | Pagination cursor from the previous response's `next_cursor`. See [Pagination](#pagination). |

### Response

Responses are wrapped in an envelope. `data` holds the events (matching the WebSocket schema for that channel) in descending time order, newest first.

```json
{
  "applied_filters": {
    "after": null,
    "before": null,
    "cursor": null,
    "exchange": null,
    "limit": 50
  },
  "data": [
    /* events, newest first */
  ],
  "next_cursor": "eyJ0IjoxNzYxNzE5NDU2OTE2LCJpIjoiMTczOTQ2MjQxNzEyOSJ9"
}
```

### Pagination

When more events match than fit in a single page, the server returns a `next_cursor` string. Pass it back as `cursor` on the next request to continue where you left off. When the last page is reached, `next_cursor` is `null`.

```bash
curl -H "authorization: Bearer YOUR_KEY" \
  "https://tokyo.newlistings.pro/v1/new-listings?limit=100&cursor=eyJ0IjoxNzYxNzE5NDU2OTE2LCJpIjoiMTczOTQ2MjQxNzEyOSJ9"
```

`cursor` can be combined with `before`, `after`, and `exchange`. Those filters stay active across pages.
