Metadata-Version: 2.5
Name: tokenearly
Version: 0.1.2
Summary: Read new crypto exchange token listings from the public Tokenearly feed. No account, no API key.
Project-URL: Homepage, https://tokenearly.com
Project-URL: Documentation, https://github.com/tokenearly/tokenearly-python#readme
Project-URL: Source, https://github.com/tokenearly/tokenearly-python
Project-URL: Issues, https://github.com/tokenearly/tokenearly-python/issues
Project-URL: Listing timeline, https://tokenearly.com/listings
Project-URL: Public feed, https://tokenearly.com/api/public/listings.json
Author: Tokenearly
License: MIT License
        
        Copyright (c) 2026 Tokenearly
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Keywords: alerts,announcements,binance,bithumb,bybit,cli,crypto,cryptocurrency,exchange,listing,listings,new-listing,okx,trading,upbit
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Topic :: Office/Business :: Financial
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Utilities
Classifier: Typing :: Typed
Requires-Python: >=3.8
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == 'dev'
Description-Content-Type: text/markdown

# tokenearly

[![PyPI](https://img.shields.io/pypi/v/tokenearly.svg)](https://pypi.org/project/tokenearly/)
[![Python versions](https://img.shields.io/pypi/pyversions/tokenearly.svg)](https://pypi.org/project/tokenearly/)
[![License](https://img.shields.io/pypi/l/tokenearly.svg)](https://github.com/tokenearly/tokenearly-python/blob/main/LICENSE)

Read new crypto exchange token listings from the command line or from Python. **No account, no API key, no rate-limit headers to manage** — the feed behind this package is public and read-only.

```console
$ pip install tokenearly
$ tokenearly listings --exchange binance --type spot --days 30
published (utc)   exchange  type  symbols   headline
----------------  --------  ----  --------  -----------------------------------------------------------
2026-09-09 11:30  Binance   spot            Binance Will List 牛来 (牛来) with Seed Tag Applied
2026-09-04 10:15  Binance   spot  MARSCOIN  Binance Will List MarsCoin (MARSCOIN) with Seed Tag Applied

2 listing(s).
```

## How do I get notified when an exchange lists a new token?

That is the question this package exists to answer. Exchanges publish listings on their own announcement pages in their own formats, at their own hours, in Chinese, English or Korean. This package reads one normalized feed covering 10+ exchanges, so you can filter and act on listings without writing a scraper per exchange.

Three ways to use it:

```console
# One-off look at what has been listed recently
tokenearly listings --days 7

# Which exchanges are covered, and how active each has been
tokenearly exchanges

# Long-running: print each new listing exactly once, then pipe it anywhere
tokenearly watch --interval 300 --json | while read -r line; do
  echo "$line" | jq -r '.exchange_name + " " + .title.en'
done
```

## Which exchanges are covered?

Binance, OKX, Bybit, Bitget, MEXC, Gate.io, HTX, KuCoin, Upbit and Bithumb. `tokenearly exchanges` prints the live list with a 30-day listing count for each, so you never have to trust a number in a README:

```console
$ tokenearly exchanges
id       name     collection  30d  spot  futures
-------  -------  ----------  ---  ----  -------
mexc     MEXC     polling     129  73    56
gate     Gate.io  websocket   44   19    25
okx      OKX      polling     32   2     30
huobi    Huobi    polling     28   13    15
kucoin   KuCoin   polling     27   20    7
bitget   Bitget   polling     18   10    8
bybit    Bybit    polling     13   5     8
upbit    Upbit    polling     11   11    0
bithumb  Bithumb  polling     7    7     0
binance  Binance  websocket   5    2     3

10+ exchanges, 314 listings in the last 30 days.
Announcements arrive over the exchange's own WebSocket stream for: gate, binance
```

These are excluded, because none of them is a new crypto token: tokenized stocks and stock perpetuals, commodity and index contracts, pre-IPO contracts, new features for tokens that are already listed (earn, loans, margin, grid and copy trading), migrations and board moves, and promotional events.

The `collection` column matters if latency does. Binance and Gate.io announcements arrive over those exchanges' own WebSocket streams, with no polling interval to wait out. The other eight are polled at high frequency.

## Python API

```python
from tokenearly import Client

client = Client()

for item in client.listings(days=1, type="spot"):
    print(item.exchange_name, item.symbols, item.headline("en"))
    print(item.source_url)      # the exchange's own announcement
    print(item.permalink)       # stable URL, also a good dedupe key

# Titles come in three languages, so no second request is needed
item = client.listings(days=7, limit=1)[0]
item.headline("zh")
item.headline("ko")

# Coverage and how each exchange is collected
for ex in client.exchanges():
    print(ex.id, ex.listings_30d, "websocket" if ex.websocket else "polling")
```

`watch()` is a generator that yields each listing once:

```python
from tokenearly import Client

for item in Client().watch(interval=300, exchange="upbit"):
    notify(f"{item.exchange_name}: {item.headline('ko')}")
```

Dedupe inside `watch()` is by permalink and lives in memory. Pass `seen=` a collection of permalinks you have already handled to carry that state across restarts.

### Listing fields

| Field | Meaning |
|---|---|
| `exchange` | exchange id, for example `binance` |
| `exchange_name` | display name, for example `Binance` |
| `type` | `spot` or `futures` |
| `symbols` | token symbols found in the announcement, for example `["ARB"]` |
| `published_at` | ISO 8601 UTC timestamp from the exchange |
| `title` | headline keyed by language: `en`, `zh`, `ko` |
| `source_url` | the exchange's own announcement page |
| `permalink` | stable URL for this announcement |
| `raw` | the untouched feed object, for anything not mapped above |

Use `Listing.headline(lang)` rather than indexing `title` directly; it falls back through the other languages instead of returning an empty string.

## Design notes

**Standard library only.** No `requests`, no `pydantic`, nothing to resolve. `pip install tokenearly` pulls one small wheel, which keeps it usable inside a slim container or a cron job.

**Bad arguments fail locally.** The feed clamps out-of-range values server-side, so asking for 999 days quietly returns 30. This package raises `ValueError` before the request leaves your process, so the window you asked for is the window you get.

**A 4xx is not retried.** Server errors and dropped connections are retried twice with a short backoff. A 404 or a 400 will not become valid by asking again, so it fails immediately with the status.

**`watch()` survives an outage.** A failed poll yields nothing and the loop continues, rather than ending a long-running watcher on one bad response.

## The feed itself

If you would rather not use Python at all, the same data is three plain HTTP endpoints, all unauthenticated, cached for five minutes, CORS open:

| Endpoint | Returns |
|---|---|
| [`/api/public/listings.json`](https://tokenearly.com/api/public/listings.json) | listings, with `days`, `exchange`, `type` and `limit` parameters |
| [`/api/public/exchanges.json`](https://tokenearly.com/api/public/exchanges.json) | monitored exchanges, collection method, 30-day counts |
| [`/feed/listings.xml`](https://tokenearly.com/feed/listings.xml) | the same listings as RSS 2.0 |

The feed carries headlines, category, timestamp, token symbols and a link to the original announcement. Announcement bodies are not reproduced. Data is published under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/); attribute as *Data by Tokenearly (https://tokenearly.com)*.

There is also an [n8n template](https://github.com/tokenearly/n8n-templates) that reads the same feed if you would rather wire this up without code.

## Development

```console
git clone https://github.com/tokenearly/tokenearly-python
cd tokenearly-python
python -m pip install -e ".[dev]"
python -m pytest -q
```

Releases are published from GitHub Actions using PyPI [trusted publishing](https://docs.pypi.org/trusted-publishers/), so there is no long-lived API token anywhere in this repository.

## Related projects

Everything Tokenearly publishes, so you can pick the entry point that fits:

- Website: [Tokenearly](https://tokenearly.com) — real-time alerts for crypto exchange token listings, announcements, news and X activity; see the [listings timeline](https://tokenearly.com/listings) and the [public listings feed](https://tokenearly.com/api/public/listings.json) (JSON, no key).
- Node.js package: [tokenearly on npm](https://www.npmjs.com/package/tokenearly) ([source](https://github.com/tokenearly/tokenearly-js)) — `npm install tokenearly`; command line and Node.js client, zero dependencies.
- n8n template: [Send new token listing alerts from 10 crypto exchanges to Telegram, Discord and Google Sheets](https://n8n.io/workflows/19448-send-new-token-listing-alerts-from-10-crypto-exchanges-to-telegram-discord-and-google-sheets/) ([source](https://github.com/tokenearly/n8n-templates)) — import-ready workflow, no code.
- Webhook receivers: [webhook-examples](https://github.com/tokenearly/webhook-examples) — the Tokenearly webhook payload schema and receivers for FastAPI, Express and Cloudflare Workers.
- Signal SDK: [signal-sdk](https://github.com/tokenearly/signal-sdk) — Python and TypeScript clients for pushing your own signals into Tokenearly.
- Curated list: [awesome-crypto-listing-alerts](https://github.com/tokenearly/awesome-crypto-listing-alerts) — exchange announcement pages, listing alert tools, open-source bots and research on the listing effect.
- GitHub organization: [github.com/tokenearly](https://github.com/tokenearly) — all repositories (organization profile: [.github](https://github.com/tokenearly/.github)).
- Telegram: official channel [@tokenearly_channel](https://t.me/tokenearly_channel), official bot [@tokenearly_bot](https://t.me/tokenearly_bot).

## License

MIT

---

Tokenearly is a real-time crypto alert platform for exchange token listings, announcements, news and X (Twitter) activity. It monitors 10+ crypto exchanges (Binance, OKX, Bybit, Bitget, MEXC, Gate.io, HTX, KuCoin, Upbit, Bithumb) — Binance and Gate.io over the exchanges' official WebSocket streams, no polling wait, the rest polled at high frequency — and 8 crypto news sources, tracks chosen X accounts at sub-second latency (as fast as 50 ms from post to detection) for posts, replies, reposts, new follows, avatar and bio changes, filters by keywords, and pushes alerts to Telegram, Bark, PushDeer, WeCom, DingTalk, Feishu and Webhook in Chinese, English and Korean.
