Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,80 @@ BETFAIR_JURISDICTION=
# prohibited.
SMARKETS_USERNAME=
SMARKETS_PASSWORD=

# Novig: market data needs nothing. To trade, a subaccount's trading key: its
# key id and its private key file (PKCS#8 PEM, Ed25519 or P-256). Make the
# management key in the web app (Profile -> Settings -> Novig API), then open a
# subaccount with it (NovigTrading.open_subaccount), which issues the trading
# key. The management key (optional here) opens, funds and labels subaccounts
# and never places an order. NOVIG_ENV is production (real money, US identity
# and location checks; Arizona, Michigan and Nevada are restricted) or paper
# (play money at paper.novig.com). A key works only in the environment it was
# made in.
NOVIG_KEY_ID=
NOVIG_PRIVATE_KEY_PATH=
NOVIG_ENV=
NOVIG_MANAGEMENT_KEY_ID=
NOVIG_MANAGEMENT_PRIVATE_KEY_PATH=

# Matchbook (market data, a polled stream, and order entry): market data needs
# no login at all. Betting logs in with your Matchbook username and password;
# an account with two-factor login cannot log in from here. Every GET is
# chargeable on Matchbook's API plans (Β£100 per million a month), and its terms
# allow viewing prices and betting on your own account only.
MATCHBOOK_USERNAME=
MATCHBOOK_PASSWORD=

# ProphetX: every call, market data included, needs a key. The Trading API key
# pair (any KYC-approved account: prophetx.co -> Menu -> API Integration; the
# secret is shown once) reads market data, streams it and places orders; run
# each process on its own pair, since ProphetX counts sessions per key.
# PROPHETX_AFFILIATE_KEY (optional) is a Market Data API key that ProphetX's
# market data team issues on request; it reads market data only.
# PROPHETX_SANDBOX=1 uses ProphetX's sandbox, whose keys are made on
# sandbox.prophetx.dev.
PROPHETX_ACCESS_KEY=
PROPHETX_SECRET_KEY=
PROPHETX_AFFILIATE_KEY=
PROPHETX_SANDBOX=

# Azuro (onchain sports betting pool): market data needs nothing. To bet, the
# private key of the wallet that signs each bet and holds the bet token (USDT on
# Polygon, WETH on Base); the wallet must also approve Azuro's relayer to spend
# the token once (AzuroTrading.approve(), an on-chain transaction). AZURO_CHAIN
# picks the pool: polygon (default), base, or the testnets polygon_amoy and
# base_sepolia. AZURO_AFFILIATE (optional) is the affiliate address each bet
# names, the wallet's own when unset. AZURO_RPC_URL (optional) is the node the
# balance and allowance are read from and the approval is sent through. Azuro's
# bet API and streams are refused from some regions.
AZURO_PRIVATE_KEY=
AZURO_CHAIN=
AZURO_AFFILIATE=
AZURO_RPC_URL=

# Myriad: market data needs nothing. MYRIAD_PRIVATE_KEY is the wallet your
# Myriad account is connected to: it signs every order and cancel. An API key
# and its secret (Myriad Account settings; the secret is shown once) sign the
# account's requests and raise the rate limit; the venue refuses a key without
# its secret. Without a key the wallet signs in for a session instead, and a
# wallet's first sign-in creates its Myriad account. A key alone reads the
# account: set MYRIAD_ACCOUNT_ADDRESS (the wallet's public 0x address, not its
# private key). MYRIAD_RPC_URL (optional) is the BNB Chain node the balance is
# read from.
MYRIAD_PRIVATE_KEY=
MYRIAD_API_KEY=
MYRIAD_API_SECRET=
MYRIAD_ACCOUNT_ADDRESS=
MYRIAD_RPC_URL=

# Gemini Predictions (Gemini Titan): market data and the market stream need
# nothing. To trade, an API key from exchange.gemini.com/settings/api on a
# Gemini account with Prediction Markets access (US) that has accepted the
# current Prediction Markets terms: account-scoped, Trader role, with "Uses a
# time-based nonce" ticked (the WebSocket takes no other kind). The secret is
# shown once. GEMINI_ACCOUNT names the subaccount a master key acts for (REST
# only). GEMINI_ENV=sandbox uses api.sandbox.gemini.com with a sandbox key.
GEMINI_API_KEY=
GEMINI_API_SECRET=
GEMINI_ACCOUNT=
GEMINI_ENV=prod
24 changes: 21 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# Synpath – One API for prediction markets <a href="https://x.com/Synpath_Dev"><img src="https://img.shields.io/twitter/url?url=https%3A%2F%2Fx.com%2FSynpath_Dev&style=social&label=Follow" alt="Follow @Synpath_Dev on X" height="28"></a>

**Build on prediction markets without building against each one.**<br/>
One open-source API across 8 venues (Kalshi, Polymarket, Polymarket US, Opinion, Hyperliquid, predict.fun, Limitless and SX Bet): market data, order entry, live streams, and an execution engine that remembers what it sent. In-process from Python, over REST and WebSocket from anywhere.
One open-source API across 16 venues (Kalshi, Polymarket, Polymarket US, Opinion, Hyperliquid, predict.fun, Limitless, SX Bet, Myriad and Gemini, and the sports betting venues Betfair, Smarkets, Novig, Matchbook, ProphetX and Azuro): market data, order entry, live streams, and an execution engine that remembers what it sent. In-process from Python, over REST and WebSocket from anywhere.

<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License: MIT"></a>
<a href="https://pepy.tech/projects/synpath"><img src="https://img.shields.io/pepy/dt/synpath?label=Total%20Downloads&color=blue" alt="Total Downloads"></a>
Expand Down Expand Up @@ -80,16 +80,34 @@ No silent gaps: if we weren't recording at a moment, you get the reason instead
| | [predict.fun](https://predict.fun) | `predict_fun` | βœ“ (API key) | βœ“ | WebSocket (API key) | one book per market, both sides read it |
| | [Limitless](https://limitless.exchange) | `limitless` | βœ“ | βœ“ | WebSocket | one book per market, both sides read it |
| | [SX Bet](https://sx.bet) | `sx_bet` | βœ“ sports | βœ“ | WebSocket | one book per market, both sides read it |
| | [Gemini Predictions](https://www.gemini.com/predictions) | `gemini` | βœ“ no account, sports taxonomy | βœ“ US accounts with Prediction Markets access | WebSocket (no key for books) | one book per contract, in YES space |
| | [Betfair Exchange](https://www.betfair.com/exchange) | `betfair` | βœ“ your own account and app key (delayed key: 1-180 s late, 3 levels) | β€” | Exchange Stream API (TLS socket) | one book per runner, back and lay read as YES |
| | [Smarkets](https://smarkets.com) | `smarkets` | βœ“ no account (quotes delayed without a login) | β€” | polled from REST quotes | one book per contract, bids are YES bids |
| | [Novig](https://novig.com) | `novig` | βœ“ sports, no key | βœ“ (US, identity and location checks; Paper for play money) | WebSocket (trading key), else polled from the public book | one book per market, both sides read it |
| | [Matchbook](https://www.matchbook.com) | `matchbook` | βœ“ no account | βœ“ your own login | polled from REST | one book per runner, back and lay read as YES |
| | [ProphetX](https://www.prophetx.co) | `prophetx` | βœ“ sports (Trading API key pair, or a Market Data API key) | βœ“ | WebSocket (Trading API key pair) | one book per line, both sides read it |
| | [Azuro](https://azuro.org) | `azuro` | βœ“ sports, no key | βœ“ bets with a worst price | WebSocket (no key) | no book: the pool's quoted odds, one level a side sized by its limits |
| | [Myriad](https://myriad.markets) | `myriad` | βœ“ order-book and AMM markets, sports | βœ“ order book | WebSocket (no key) | one book per market, both sides read it; AMM books built from the pool |

Betfair is a betting exchange, not a prediction market, read here the same way: each runner (selection) is a yes/no market, `betfair:1.234567890-47972`, and the Betfair market holding the runners is the event. Every Betfair call needs your own Betfair account and application key, and the API is refused from several countries (the US, Germany, France, the Netherlands, Singapore, India, Turkey, the UAE and others). Betfair's keys are for your own betting: showing its prices to anyone else needs a data licence from Betfair. See [capabilities](docs/capabilities.md#betfair).

Gemini Predictions is Gemini Titan's CFTC-registered event-contract exchange. Each contract is a yes/no market named by its instrument symbol, `gemini:GEMI-NBA-2610232000-CHI-MIL-M-MIL`, and the Gemini event holding the contracts is the event. Sports events carry Gemini's taxonomy (moneyline, spread, total, prop; the sport, scope and statistic), which listings filter on. Market data needs no account; trading needs a Gemini account with Prediction Markets access (US) and an API key. See [capabilities](docs/capabilities.md#gemini).

Smarkets, a UK betting exchange, is read the same way: each contract is a yes/no market, `smarkets:164973231-456060183`, and the Smarkets market holding the contracts is the event. Its market data needs no account (quotes are delayed without a login); betting needs Smarkets' approved API access, which this library does not use yet. Smarkets' API terms allow viewing prices and betting on your own account, and prohibit odds scraping. See [capabilities](docs/capabilities.md#smarkets).

Novig, a US sports exchange, lists two-outcome markets (a moneyline, a spread, a total, a Yes/No prop), each one yes/no market, `novig:01a1577c-d666-7e81-852e-68bed1446801`, under its game as the event. Its catalog, books and trades are public and need no key. Trading signs each request with a subaccount's key; Production trades real money for verified US customers outside Arizona, Michigan and Nevada, and Paper (`NOVIG_ENV=paper`) is the same API with play money. Novig's parlay RFQ, for registered liquidity providers, is not supported yet. See [capabilities](docs/capabilities.md#novig).

Matchbook, a betting exchange licensed in the UK and Alderney, is read the same way: each runner is a yes/no market, `matchbook:<event id>-<market id>-<runner id>`, and the Matchbook market holding the runners is the event. Its market data needs no account; betting logs in with your own Matchbook username and password. Every GET is chargeable on Matchbook's API plans (Β£100 per million a month), and its terms allow viewing prices and betting on your own account only. See [capabilities](docs/capabilities.md#matchbook).

ProphetX, a US peer-to-peer sports exchange, is read the way SX Bet is: each line (a moneyline, or a spread or total at one number) is a yes/no market whose first side is YES, `prophetx:44285780-90de769f4f4977a04446ed203e957351` (the event, then the YES side's strike id), and the game is the event. Prices are American odds, converted exactly to probabilities. Every call needs a key: the Trading API key pair, which any KYC-approved ProphetX account generates under API Integration, or a Market Data API key issued by ProphetX on request. See [capabilities](docs/capabilities.md#prophetx).

Azuro is an onchain sports betting protocol: a shared liquidity pool takes every bet at the odds it quotes, so there is no order book and nothing rests. A two-outcome condition ("Total Goals Over/Under 2.5") is one yes/no market, `azuro:<conditionId>`, with the lower outcome id as YES; a condition with three or more outcomes (1X2, correct score) is one market per outcome, `azuro:<conditionId>-<outcomeId>`, where only YES can be bought. The game is the event. Prices are `1 / odds`. Ids are the same on every chain; `Azuro(chain=...)` picks the pool read (Polygon USDT by default, Base WETH). Bets are EIP-712 messages signed by your wallet and placed on chain by Azuro's relayer. Azuro's bet API and streams are refused from some regions. See [capabilities](docs/capabilities.md#azuro).

Myriad runs order-book markets on BNB Chain and AMM (pool) markets on BNB Chain, Abstract and Linea behind one API. A market id carries its network, and `amm` for a pool market, since the two kinds number their markets separately: `myriad:56-2385` is an order-book market, `myriad:56-amm-2385` an unrelated pool market. Order entry is on the order book; a pool trade is an on-chain transaction this library does not send. See [capabilities](docs/capabilities.md#myriad).

## Why Synpath

- **Liquidity is fragmented. Your time shouldn't be.** The same market trades on Kalshi, Polymarket, Polymarket US, Opinion, Hyperliquid, predict.fun, Limitless and SX Bet, each with its own API, units and quirks. Synpath gives you one interface for all of them, and smart order routing buys from whichever book is cheapest. Spend your time on alpha, not plumbing.
- **Liquidity is fragmented. Your time shouldn't be.** The same market trades on Kalshi, Polymarket, Polymarket US, Opinion, Hyperliquid, predict.fun, Limitless, SX Bet, Myriad and Gemini, and the sports betting venues Betfair, Smarkets, Novig, Matchbook, ProphetX and Azuro, each with its own API, units and quirks. Synpath gives you one interface for all of them, and smart order routing buys from whichever book is cheapest. Spend your time on alpha, not plumbing.

- **Traders deserve advanced order types.** Stops, trailing stops, icebergs, OCO, brackets, TWAP and pegs, on every venue, even where the exchange has none. Orders are journaled before they're sent, so a crash never places one twice.

Expand Down Expand Up @@ -135,7 +153,7 @@ fee.estimate(price=0.50, contracts=100) # 1.75
**Same code, every venue**

```python
for venue_id in synpath.exchanges: # [..., 'sx_bet', 'betfair', 'smarkets'] (Betfair and predict.fun need keys)
for venue_id in synpath.exchanges: # [..., 'betfair', 'smarkets', 'novig', 'matchbook', 'prophetx', 'azuro', 'myriad', 'gemini'] (Betfair, predict.fun and ProphetX need keys)
with synpath.exchange(venue_id) as venue:
page = venue.fetch_markets(limit=5)

Expand Down
Loading
Loading