CCXT vs the CoinEx API
CoinEx ships sample code, not an installable SDK. CCXT versus the raw v2 REST and WebSocket API on signing, rate limits, streaming and portability.
CoinEx documents a v2 REST and WebSocket API at docs.coinex.com and publishes coinex_api_demo — sample code in C#, Go, Node.js, Python and Rust. What it does not publish is an installable client library: the demo repository is reference code you copy, and its README points back at the documentation.
So the choice here is not "CCXT or the vendor SDK". It is CCXT or your own HTTP client, and the question that decides it is how much of the signing, throttling and order-book plumbing you want to own.
TL;DR
- Write against the raw API if you need one or two endpoints, want zero dependencies, and are comfortable implementing HMAC-SHA256 signing and a rate limiter yourself.
- Pick CCXT if you want CoinEx spot, margin and futures behind one client that already handles signing, per-endpoint throttling, gzip-framed WebSocket frames and order-book resync — and that speaks the same API on 103 other venues.
- Choosing CCXT does not hide anything. All 251 CoinEx endpoints are generated as implicit methods, so nothing in the raw API is out of reach.
At a glance
| CCXT | Raw CoinEx API | |
|---|---|---|
| Exchanges covered | 104 (CoinEx is one of them) | CoinEx only |
| Languages | TypeScript, JavaScript, Python, PHP, C#/.NET, Go, Java — one API | any; sample code in C#, Go, Node.js, Python, Rust |
| Installable client library | yes — ccxt | none published; coinex_api_demo is copy-paste sample code |
| Unified market data + trading API | yes — 72 unified capabilities, 35 fetch* methods | CoinEx's own request/response shapes |
| WebSockets | yes — 10 watch* methods, gzip frames decoded for you | yes — wss://socket.coinex.com/v2/spot and /v2/futures, raw |
| Raw endpoint access | yes — 251 endpoints as implicit methods | it is the whole product |
| Built-in rate limiter | yes, per-endpoint weights, on by default (rateLimit 2.5ms) | you model 400 req/s per IP plus per-account limits |
| Unified error types | yes — 41 typed exceptions in one hierarchy | HTTP status plus CoinEx code values |
| Testnet / sandbox | not available for CoinEx | none documented |
| Popularity | 43.8k GitHub stars · 4.8M PyPI + 494k npm installs/month (one package, every venue) | coinex_api_demo 22 stars; coinex_exchange_api docs repo 196 stars |
| Licence | MIT | n/a |
| Support | Discord, Telegram, GitHub issues — usually same-day | CoinEx support ticket, docs site |
Figures verified September 2026 against CCXT v4.5.77, the CoinEx v2 API documentation, and the repositories published by the coinexcom GitHub organisation.
The same job, written both ways
Fetch a ticker
import ccxt
exchange = ccxt.coinex()
ticker = exchange.fetch_ticker('BTC/USDT')
print(ticker['last'], ticker['baseVolume'])The raw call is short because public market data is unsigned. CCXT returns a unified ticker structure — same keys, same types, same units as on every other venue — and you did not have to know that CoinEx wraps its payload in data and calls quote volume value.
Place a limit order
import ccxt
exchange = ccxt.coinex({'apiKey': '...', 'secret': '...'})
order = exchange.create_order('BTC/USDT', 'limit', 'buy', 0.001, 60000)
print(order['id'], order['status'])CoinEx signs method + request_path + body + timestamp with HMAC-SHA256 and expects the digest as lowercase hex in X-COINEX-SIGN. That is not hard, but it is exactly the kind of code that breaks silently: get the body serialisation wrong by one character and every private call fails authentication. CCXT implements it once, per venue, and it is tested on every release.
Switching that same order to futures is one option change, not a new signing path:
exchange = ccxt.coinex({'apiKey': '...', 'secret': '...',
'options': {'defaultType': 'swap'}})
order = exchange.create_order('BTC/USDT:USDT', 'limit', 'buy', 0.001, 60000)Stream an order book
import ccxt.pro
import asyncio
async def main():
exchange = ccxt.pro.coinex()
while True:
orderbook = await exchange.watch_order_book('BTC/USDT')
print(orderbook['bids'][0], orderbook['asks'][0])
asyncio.run(main())These two snippets are not doing the same job. CCXT returns a live, merged order book; the raw socket returns update messages that you must decompress, apply to a local snapshot in the right order, and re-seed after a gap or a reconnect.
| CCXT | raw stream | |
|---|---|---|
| Decompress the gzip-framed messages | done for you | your code |
| Merge depth updates into a full book | done for you | your code |
| Detect gaps and re-subscribe from a fresh snapshot | done for you | your code |
Keep the connection alive (server.ping) | done for you | your code |
| Reconnect and re-subscribe after a drop | done for you | your code |
| Bounded caches instead of unbounded growth | done for you | your code |
Where the differences actually bite
Rate limits you do not have to model
CoinEx applies a 400 requests per second limit per IP on top of per-account short-cycle limits that differ by endpoint group — 30 r/s to place or edit spot orders, 60 r/s to cancel, 50 r/s to query orders, but only 10 r/s for spot order history, and 20 r/s to place or edit futures orders. Batch requests consume quota per sub-request, and there are additional long-cycle windows measured over 1, 4, 8 and 24 hours.
CCXT encodes per-endpoint weights in the exchange definition and ships a throttler that is on by default (enableRateLimit = true, rateLimit = 2.5ms). You call methods in a loop; the library paces them.
One error hierarchy
CoinEx returns a numeric code in the response body. CCXT maps those onto a typed exception tree — InsufficientFunds, InvalidOrder, OrderNotFound, RateLimitExceeded, AuthenticationError, NetworkError and 35 more, all descending from BaseError. You write except ccxt.InsufficientFunds once, and it keeps working when you add a second exchange.
Precision and string math
CoinEx rejects orders that violate tick size, step size or minimum notional. CCXT loads market metadata and gives you amount_to_precision, price_to_precision and cost_to_precision, backed by the Precise string-arithmetic class so quantities never drift through float rounding.
amount = exchange.amount_to_precision('BTC/USDT', 0.0012345678)
price = exchange.price_to_precision('BTC/USDT', 61234.56789)Portability is the whole point
Adding a second venue to a hand-rolled CoinEx integration means a second signing scheme, a second symbol convention, a second error taxonomy and a second WebSocket dialect. That translation layer is what CCXT already is, across 104 venues:
for exchange_id in ['coinex', 'binance', 'okx', 'bybit', 'kucoin']:
exchange = getattr(ccxt, exchange_id)()
print(exchange_id, exchange.fetch_ticker('BTC/USDT')['last'])Nothing is hidden — the implicit API
Alongside the 72 unified capabilities CCXT implements for CoinEx, all 251 endpoints in its API block are generated as callable implicit methods, with signing, rate-limit accounting and error mapping applied:
response = exchange.v2PublicGetSpotTicker({'market': 'BTCUSDT'})Browse the full list on the CoinEx implicit API page.
What the raw CoinEx API does better
Honest advantages of going direct:
- Zero dependencies and a smaller footprint. A single signed
requestscall has no library between you and the venue. If your service reads one endpoint on a schedule, CCXT is more machinery than the job needs. - The demo repository covers five languages CoinEx tested itself.
coinex_api_demohas working signing examples in C#, Go, Node.js, Python and Rust — useful if you are porting the signer into a language or runtime CCXT does not target. - New endpoints are usable the day they ship. A brand-new CoinEx endpoint is callable by URL immediately; a unified CCXT wrapper for it may follow later. (CCXT's implicit API closes most of this gap, but only after the endpoint is added to the exchange's API block.)
- Field-for-field fidelity with the docs. Reading the CoinEx reference and calling the endpoint directly means what you see in the docs is what you get back. CCXT's unified names are a deliberate abstraction, which is one extra hop when debugging.
If CoinEx is your only venue, you need a couple of endpoints, and you would rather own 60 lines of signing code than add a dependency, going direct is a defensible choice.
Migrating from the raw CoinEx API to CCXT
| What you are doing | Raw CoinEx API | CCXT |
|---|---|---|
| Symbols | 'BTCUSDT' | 'BTC/USDT' (spot), 'BTC/USDT:USDT' (futures) |
| Product selection | different path prefix and market type | options.defaultType = spot / margin / swap |
| Market list | GET /v2/spot/market | load_markets() |
| Ticker | GET /v2/spot/ticker | fetch_ticker() / fetch_tickers() |
| Order book | GET /v2/spot/depth | fetch_order_book() |
| Candles | GET /v2/spot/kline | fetch_ohlcv() |
| New order | POST /v2/spot/order | create_order() |
| Cancel order | POST /v2/spot/cancel-order | cancel_order() |
| Open orders | GET /v2/spot/pending-order | fetch_open_orders() |
| Balance | GET /v2/assets/spot/balance | fetch_balance() |
| Streams | wss://socket.coinex.com/v2/spot | watch_* on ccxt.pro.coinex |
| Anything not listed | the endpoint URL | the same endpoint as an implicit method |
FAQ
Does CoinEx have an official Python SDK?
Not an installable one. CoinEx publishes coinex_api_demo, a repository of sample scripts in C#, Go, Node.js, Python and Rust, and points developers at docs.coinex.com. If you want a maintained client library for CoinEx, CCXT is the practical option.
Does CCXT support CoinEx futures and margin?
Yes. Spot, margin and futures are all served by one ccxt.coinex instance, selected with options.defaultType and unified params. CCXT implements 72 unified capabilities for CoinEx, including positions, leverage, funding rates, leverage tiers and margin adjustment history.
Does CCXT stream CoinEx over WebSocket?
Yes — 10 watch* methods: watchOrderBook, watchOrderBookForSymbols, watchTicker, watchTickers, watchBidsAsks, watchTrades, watchTradesForSymbols, watchOrders, watchMyTrades and watchBalance. CCXT decompresses the gzip-framed messages and maintains the merged order book for you.
Is there a CoinEx testnet I can use with setSandboxMode?
No. CCXT's CoinEx class does not declare a sandbox, because CoinEx does not publish testnet base URLs. Test against small live orders or against static fixtures instead.
Can I still call CoinEx-specific endpoints through CCXT? Yes — all 251 of them, as implicit methods, with signing, throttling and error mapping applied.
Is CCXT free? Yes. MIT-licensed, including the WebSocket support.
Next steps
- Install CCXT in your language
- Manual — the unified API, structures and conventions
- coinex unified API reference
- coinex implicit API — every raw endpoint
- CCXT Pro manual — WebSocket methods
- More comparisons
CCXT vs the Coincheck API and the coincheckjp libraries
Coincheck publishes client libraries in seven languages, most years old. Compare them with CCXT on upkeep, market coverage, streaming and rate limits.
CCXT vs the Coinmate API
Coinmate publishes copy-paste API clients rather than installable packages. Compared with CCXT on signing, coverage, dependencies and portability.