pax-api — Official Python SDK for PredictAsiaX
Web3-native prediction market REST + WebSocket API client. Polymarket-compatible HMAC signing pattern.
Version 2.2.1 · MIT license · Python 3.8+
- Docs: https://docs.predictasiax.com
- Verify: https://docs.predictasiax.com/verify — public Merkle verifier over the operational ledger
- Get API key: https://predictasiax.com/settings/api-keys
- Sandbox key (anonymous, 30 seconds):
POST /v1/sandbox-keys - Support: support@predictasiax.com
Install
pip install pax-api
Upgrade:
pip install --upgrade pax-api
Quickstart — sandbox key in 30 seconds (no email)
from pax_api import PaxClient
# Mint an anonymous sandbox key
with PaxClient(env="sandbox") as pax:
res = pax.mint_sandbox_key(org_name="my-app")
key = res["data"]["api_key"]
tier = res["data"]["tier"] # e.g. "self_serve"
limits = res["data"]["limits"] # e.g. {"per_order_usdt": 10, "per_day_usdt": 100}
# Use the key
with PaxClient(api_key=key, env="sandbox") as pax:
markets = pax.list_markets(category="crypto", limit=10)
for m in markets["data"]["items"]:
print(m["market_id"], m["question"])
Same production host either way (api.predictasiax.com/v1). Sandbox tier is enforced on the key — no prefix magic.
Production trading (HMAC-signed)
Machine-to-machine bots use HMAC signing (Polymarket-compatible 5-header pattern):
from pax_api import PaxClient
pax = PaxClient(
api_key="sk_live_YOUR_KEY",
secret="<64-hex secret>",
passphrase="<passphrase>",
env="production",
)
pax.place_order(
market_id="m_...",
outcome_id="yes",
side="buy",
order_type="limit",
size="100",
price="0.55",
client_order_id="unique-per-intent-id", # retry-safe within 24h
)
Batch orders
Place or cancel up to 25 orders / 50 cancels per call:
res = pax.place_orders_batch([
{"market_id": "m_a", "outcome_id": "yes", "side": "buy", "order_type": "limit", "size": "10", "price": "0.55"},
{"market_id": "m_b", "outcome_id": "no", "side": "sell", "order_type": "limit", "size": "20", "price": "0.42"},
])
for item in res["data"]["results"]:
print(item["ok"], item.get("order_id"), item.get("error"))
pax.cancel_orders_batch([o["order_id"] for o in res["data"]["results"] if o["ok"]])
Env-driven caps: BATCH_ORDERS_MAX (default 25), BATCH_CANCEL_MAX (default 50).
Fee estimator
Preview the 5-actor fee split before you place a trade — same shape returned post-trade:
est = pax.estimate_fees(size="100", price="0.55")
print(est["data"]["fee_ledger"])
# {
# "acquisition_builder_bps": 10, "execution_builder_bps": 10,
# "operator_bps": 5, "market_creator_bps": 8, "lp_bps": 12,
# "platform_net_bps": 5, "total_bps": 50,
# "amounts": {"acquisition_builder": "0.055", ...},
# "ledger_preview": {...}
# }
Public Merkle verifier
Every fill is recorded in a hash-chained event_log, batched into a Merkle tree, and anchored to a public URL (R2). You (or any third party) can independently verify inclusion — no auth required.
status = pax.audit_status()
print(status["data"])
# {"events": 110914, "batches": 7232, "anchored": 7231, ...}
# Get an inclusion proof for event seq=42
proof = pax.audit_proof(42)
leaf = proof["data"]["leaf"]
root = proof["data"]["root"]
path = proof["data"]["proof"]
# Verify client-side (no server round-trip needed)
assert PaxClient.verify_merkle_proof(leaf=leaf, root=root, proof=path)
# Optional: fetch the signed batch anchor
anchor = pax.audit_anchor(proof["data"]["batch_num"])
print(anchor["data"]["url"]) # publicly fetchable
See https://docs.predictasiax.com/verify for the browser-side demo + 4-language snippets.
WebSocket streams
from pax_api import PaxWSClient
ws = PaxWSClient(
api_key=key,
env="sandbox",
subscribe_on_connect=["fast_tick", "trade_executed", "account"],
)
ws.on("fast_tick", lambda e: print("tick:", e))
ws.on("trade_executed", lambda e: print("trade:", e))
ws.on("account", lambda e: print("balance:", e.get("balance_free")))
ws.run_forever() # blocks; Ctrl+C to exit
Auto-reconnect + exponential backoff built-in. Client methods supported: subscribe, unsubscribe, auth, set_locale.
Error handling
Every response error becomes a typed exception:
from pax_api import (
PaxClient,
PaxRateLimitError,
PaxReadOnlyModeError,
PaxValidationError,
PaxWrongEnvKeyError,
PaxError, # base class — catch-all
)
try:
pax.place_order(...)
except PaxRateLimitError as e:
time.sleep(e.retry_after or 5)
except PaxValidationError as e:
print(f"Bad request: {e.details}")
except PaxReadOnlyModeError:
print("Trading paused by ops")
except PaxWrongEnvKeyError:
print("Wrong environment key")
except PaxError as e:
print(f"[{e.code}] {e.message} (request_id={e.request_id})")
Automatic retry
Built-in exponential backoff on 429, 500, 502, 504. Retry-After header respected on rate limits. Non-idempotent creates are safe when you send client_order_id.
pax = PaxClient(api_key=key, env="sandbox", max_retries=5)
# max_retries=0 disables retries entirely
Environments
| Env | Base URL |
|---|---|
production |
https://api.predictasiax.com/v1 |
sandbox |
https://api.predictasiax.com/v1 |
Sandbox and production share the same host. Sandbox tier is enforced on the key (tier=self_serve), which caps per-order / per-day USDT — see the POST /v1/sandbox-keys response limits field.
Custom base URL
pax = PaxClient(api_key="...", base_url="https://your-mirror/api/v1")
Applications (progressive trust)
Move from sandbox → trade-capped → trade-full by submitting an application:
res = pax.apply(track="trader", org="my-org", contact="team@my-org.io")
print(res["data"]["application_code"]) # save this
status = pax.get_application(res["data"]["application_code"])
print(status["data"]["status"]) # submitted → in_review → approved / declined
Development
git clone https://github.com/predictasiax/pax-python-sdk
cd pax-python-sdk
pip install -e ".[dev]"
pytest # run all tests
ruff check src tests # lint
mypy src # type-check
Links
- OpenAPI spec
- AsyncAPI (WebSocket) spec
- Auth guide
- Verify (public Merkle verifier)
- Error codes
- Rate limits
- FAQ
- Changelog
- API Terms
License
MIT — see LICENSE.
Release files for pax-api 2.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pax_api-2.2.1.tar.gz | 23.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pax_api-2.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 43.3 kB
Release files / pax_api-2.2.1.tar.gz
| Download URL | pax_api-2.2.1.tar.gz |
|---|---|
| Size | 23.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
604c3522bafd0e0ac9e3f5347c6d197f11793b2be4c7b1b72732a0e600512eff
|
|
BLAKE2b-256 checksum How to use checksums |
f95e52c0fcce555cfe5dfc7489f49dea3da0da8d36c0b74eef282c4a4c3b46c7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.6
|
Release files / pax_api-2.2.1-py3-none-any.whl
| Download URL | pax_api-2.2.1-py3-none-any.whl |
|---|---|
| Size | 19.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
87957f7bb9702c1d7a7a45b3bb7c3963e12d204b280fc19e269a2612d3f77b13
|
|
BLAKE2b-256 checksum How to use checksums |
27ac657d01bfd95a44f1595fcdd1746bd0663ec40c7de706ed2efb399ef5b878
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.6
|