Open-source project
pmxt-dev/pmxt avatar
pmxt-dev/pmxt

pmxt: fourteen prediction market venues behind one API, three of which you can trade through

CCXT for prediction markets. PMXT is a unified API for trading on Polymarket, Kalshi, and more.

2,165 stars275 forksTypeScriptMIT

At a glance

What is it?
A TypeScript monorepo that flattens prediction market data into a ccxt-shaped interface, with a hosted custody tier that supports writes on fewer venues than the banner suggests.
Who is it for?
pmxt is genuinely useful for reading across venues, since a market identifier and an order book shape that differ between operators are the actual cost of working with prediction markets directly. The hosted tier is the part to read carefully, because it holds your keys, and the only venues it will trade on today are Polymarket, Opinion and Limitless.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 11 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 11, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Fourteen venues in the banner, three with hosted write support

The README opens by calling pmxt the ccxt for prediction markets, and the repository description repeats the promise as a unified API for trading on Polymarket, Kalshi, and more. The Supported Exchanges block then lays out fourteen linked venues in a single centred table: Polymarket, Polymarket US, Kalshi, Limitless, Probable, Baozi, Myriad, Opinion, Metaculus, Smarkets, Hyperliquid, Gemini Titan, SuiBets, Rain and Hunch. Fourteen is a large number for a project whose most recent release is numbered in the low fifties, and it is the number that will show up in any comparison you read.

The number that matters for trading is three. The bullet list under Why pmxt spells it out: hosted writes cover Polymarket, Opinion, and Limitless today, and everything else is reached by self-hosting for venue-native writes such as Kalshi where supported. So the description sentence about trading on Kalshi is true only through the self-hosted path, and the difference between those two sentences is the difference between someone else's key custody and your own. Read coverage and write coverage as separate axes. A venue appearing in the logo row tells you the data adapter exists, not that pmxt can place an order for you on that venue.

Two SDKs, a CLI, and a language-agnostic HTTP fallback

Installation is three separate surfaces. The Python SDK needs Python 3.8 or newer, and the Node.js SDK needs Node 18 or newer with `node` on the PATH. The CLI is a separate global package rather than a subcommand of the Node SDK, which is a small detail that trips people up when a `pmxt` command is not found after a local install.

bash
pip install pmxt
bash
npm install pmxtjs
bash
npm install -g @pmxt/cli

The npm package is named pmxtjs while the Python package is named pmxt, and the release notes list four publishable artifacts rather than two: pmxtjs, @pmxt/cli, pmxt-core on npm and pmxt on PyPI. Anything language-specific gets an SDK, and everything else is expected to go over HTTP, which the README lists as a first-class access path rather than a fallback. There is also a drop-in codemod named dome-to-pmxt for teams migrating after a Polymarket acquisition, and an MCP endpoint so agents can call the same surface directly.

The README also points at core/COMPLIANCE.md for the per-method feature and compliance matrix, which is the file to consult before assuming any particular call is permitted on a given venue.

A monorepo whose root manifest depends on an older version of itself

The tree is small at the top level and deep below it: `core/`, `sdks/`, `docs/`, `scripts/` and `tools/`, plus ARCHITECTURE.md, MIGRATION.md, ROADMAP.md and a `feature-status.csv` at the root. There is a stray `fifa.py` sitting in the root directory next to `package.json`, which suggests the root is used as a scratch space rather than kept curated.

The root `package.json` is where the interesting inconsistency sits. It declares itself `pmxt-monorepo`, marks itself private, sets Node 18 or newer as the engine floor, and lists workspaces of `core` and `sdks/*`. Then its dependency block pulls in `pmxtjs` at `^2.17.1` while the workspace it belongs to publishes version 2.54.0. The monorepo is therefore depending on a caret range that resolves to something more than thirty releases behind its own current tag. Alongside that sit `viem` pinned twice, once as a direct dependency and again in an `overrides` block, both at 2.48.4, which is the shape you use when a transitive Ethereum library needs to be forced flat.

The practical read: the root manifest is a development harness, not a consumer manifest. Anyone copying its dependency block into their own project would pin themselves to a version line the project itself has moved well past. Pin an explicit version instead, which is exactly what the release notes show.

A credential leak that was caught before it shipped

The v2.54.0 release notes contain the most useful paragraph in the repository, because it documents a security defect in a pull request that never landed. Pull request 1614 added a Web3 authentication lifecycle for the Probable exchange, including session storage on the base class. As originally submitted it also exposed `getSession` as an HTTP or RPC endpoint that returned the full credential set of apiKey, apiSecret and passphrase keyed by a public wallet address. On a shared hosted deployment that is a complete credential disclosure, because anyone who knew a wallet address could read another user's trading secrets.

The fix was structural rather than conditional. `getSession` was added to `EXCLUDED_METHODS` in `generate-openapi.js`, which removes it from method-verbs.json, from the OpenAPI specification and from every generated SDK client. It survives only as an in-process helper. The signature-gated `loginWithSignature` stayed available because it returns credentials only after the caller proves wallet ownership, and `isSessionActive` stayed because it returns a boolean.

That is worth reading twice for anyone evaluating the hosted tier. The hosted deployment is multi-tenant by design, and this incident shows that the boundary between in-process helpers and network-reachable methods is enforced by a generation script rather than by a type system. If you self-host, you are responsible for that boundary yourself.

Release notes that admit which parts of a pull request were dropped

Two releases in a row document partial merges, which tells you more about the project's maintenance rhythm than any roadmap file. In v2.53.1 the maintainers applied only the buildable core of issue 1419, a type refinement that gives `compareMarketPrices` a precise parameter type instead of the loose `FetchMatchesParams`. The notes state plainly that a broken SDK-generator import and a `private_key=wallet_address` bug from the original branch were dropped rather than fixed. They also point out that the base method is a stub and that the concrete Router.ts behaviour is unchanged, so the change is type-only in effect.

v2.53.0 describes a community PR triage wave in which original branches carried stale reverts, file encoding corruption and compile errors, and only the intended net change was applied on top of current main. It reports test counts for the run: 816 core tests, 267 Python SDK tests and 93 TypeScript SDK tests. The new surface in that release includes a Router-level `sql()` that posts to a read-only ClickHouse endpoint with scrubbed errors, and a cross-venue order book fetch that returns a single merged `OrderBook`.

Reading these as a user, the pattern is a fast-moving project with a wide contributor base and a maintainer willing to take the compiling subset of a large PR rather than hold the release. The corollary is that a method existing in a released SDK does not guarantee it does what its name suggests, which is why feature-status.csv exists.

1376 open issues against 2173 stars

The repository metadata reports 2173 stars, 276 forks and 1376 open issues. An open issue count near two thirds of the star count is unusual, and it is consistent with the triage pattern above: a project taking contributions faster than it closes them, in a domain where every new venue adds an adapter and every venue API changes without notice.

The last push was on 2026-07-18, which is the same day as both v2.54.0 and v2.53.1. Nothing about the repository suggests the project is dormant, and it is not archived; what the dates show instead is a tight cadence in which two releases and one push land inside a two hour window, which is a sign of continuous work rather than a burst.

For an evaluator, the practical question is whether the 1376 open issues include venue breakages that matter to you. The feature matrix at core/COMPLIANCE.md and the CSV at the root are the maintained answer to that. Both live in the repository rather than on the documentation site, which is a good sign for a project whose integrations are the product.

Editorial conclusion

pmxt is genuinely useful for reading across venues, since a market identifier and an order book shape that differ between operators are the actual cost of working with prediction markets directly. The hosted tier is the part to read carefully, because it holds your keys, and the only venues it will trade on today are Polymarket, Opinion and Limitless. If you need Kalshi execution, the self-hosted server and venue-native credentials are the path, which also means the SDKs and the compliance matrix in core/COMPLIANCE.md are the documentation that matters. Start by pinning an exact version, then check the feature-status.csv file for the specific venue and method you care about before writing any trading code.

Frequently asked questions

Can pmxt place trades on Kalshi?

Not through the hosted tier. The README states that hosted writes cover Polymarket, Opinion and Limitless today, and that venue-native writes such as Kalshi are reached by self-hosting the local server with your own credentials. Data access for Kalshi is available through the unified interface, so the distinction that matters is execution rather than reads.

What is the difference between the hosted pmxt API and the self-hosted server?

The hosted API keeps custody, signing infrastructure and on-chain settlement on pmxt's side, so you hold a key from the dashboard rather than a wallet key. The self-hosted option runs the local server on your own machine with your own venue credentials and no pmxt in the loop. Both expose the same SDK surface, which is why the venue list and the hosted write list differ.

How does pmxt compare with ccxt?

ccxt normalizes spot and derivatives exchanges that share a trade and order book vocabulary. Prediction markets do not share that vocabulary cleanly, because outcomes are tokens, prices are probabilities and settlement is often on-chain, so pmxt is a separate library with its own types rather than a ccxt plugin. The relationship is that pmxt borrows ccxt's idea of one interface across venues rather than its code.

Which credentials does pmxt need for Polymarket?

The bundled .env.example lists a Polymarket private key for signing transactions, plus a CLOB API key, API secret and passphrase from the Polymarket developer portal. A funder address and a signature type are listed as optional, with the signature type defaulting to gnosis-safe. The same file shows that Kalshi wants an RSA private key while Opinion and Limitless want an Ethereum private key, so credential shapes do not match across venues.

Official sources

  1. License: MIT
  2. pmxt-dev/pmxt on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/pmxt-dev-pmxt.svg)](https://hysenlabs.com/projects/pmxt-dev-pmxt)