Developer documentation
The open interface of the prediction-market exchange. The narrative is one order loop: log in with a wallet → discover markets → read the book → check the balance → place an order → poll read-your-writes to a terminal state. Market makers get batch operations, a kill switch and cancel-on-disconnect on top; real-time data is a per-topic subscription stream.
| Service | Base URL | Prefix | Auth | Purpose |
|---|---|---|---|---|
| Trading API | http://127.0.0.1:8090 | /api/v1 | Bearer session | Matching-engine gateway: login, markets, book, orders, positions, settlement. The bulk of this reference. |
| Market Maker API | http://127.0.0.1:3100 | /v1/px | pxk_ API key | Batch place/cancel, kill switch, cancel-on-disconnect heartbeats. See Market Maker API. |
| Real-time stream | ws://127.0.0.1:8090 | /api/v1/stream | Public / token in subscribe frame | Prices, round events, private account notifications. See Real-time data. |
In-browser calls to the Trading API go through the same-origin proxy /api/pmj/v1/… (the gateway sends no CORS headers; the proxy forwards REST only). Switching environments changes only the host — paths and semantics are identical.
The following mechanisms define the API semantics.
A write is appended to the command log before the 202 is returned. The matching engine consumes only the log. Results are identical after a restart or replay.
A single-threaded CLOB: price priority, then time priority, filled at the maker price. The engine and the API layer have no compile-time dependency and communicate only through protocol messages.
Write responses return a cursor. A read that carries minCursor answers only once the projection has reached that position.
Prices in E4, sizes in E2, amounts in E6. Integer arithmetic end to end; floating point is used only for display.
clientOrderId is deduplicated per account; a retry never creates a second order. On heartbeat timeout the server cancels open orders; if heartbeats are disabled on the deployment, the endpoint returns 501.
Settlement state SETTLING / CONFIRMED comes from the settlement job ledger. In on-chain mode, CONFIRMED means settlement completed on-chain. Docs are generated from OpenAPI; the endpoint list is bound to the routes by contract tests.
GatewayCommand logMatching engineProjections / market dataClearingOn-chain settlement (Sui)
cursor from the response body together with the status endpoint to confirm the outcome.minCursor — nothing is promised about its structure, and it is not comparable.Units: prices in *E4 (1e-4 USD), sizes in *E2 (1e-2 shares), amounts in *E6 (1e-6 USD). Fixed-point integers throughout; no floating point in any example.
curl -X POST "http://127.0.0.1:8090/api/v1/auth/nonce" \
-H "Content-Type: application/json" \
-d '{"address":"0x…"}'
# → {nonce, message, expiresAt}
# Hand message to the wallet's signPersonalMessage as-is, then:
curl -X POST "http://127.0.0.1:8090/api/v1/auth/verify" \
-H "Content-Type: application/json" \
-d '{"address":"0x…","signature":"<sig>","bytes":"<bytes>"}'
# → {token, address, expiresAt}The server generates message — sign it verbatim, do not assemble it yourself. The token is the credential for every Bearer request that follows.
curl "http://127.0.0.1:8090/api/v1/markets?status=open&limit=20"A cross-partition list, so minCursor is not supported. Every row carries tickE4, tradeable, and the four resolution fields.
curl "http://127.0.0.1:8090/api/v1/markets/mkt-0001/book?depth=10"Levels are quoted in YES; the NO side is the complement (1−p). The book has no outcome dimension.
curl "http://127.0.0.1:8090/api/v1/accounts/0x…" \
-H "Authorization: Bearer $PMJ_TOKEN"owner must equal the session address. fillReservedE6 is seller proceeds that have filled off-chain and are settling on-chain.
curl -X POST "http://127.0.0.1:8090/api/v1/orders" \
-H "Authorization: Bearer $PMJ_TOKEN" \
-H "Content-Type: application/json" \
-d '{"marketId":"mkt-0001","outcome":"YES","side":"BUY","priceE4":5200,"sizeE2":1000,"postOnly":false,"clientOrderId":"my-idempotency-key-1"}'
# → 202 {orderId, clientOrderId, cursor, commandId}clientOrderId is optional: only by supplying it do you get idempotent retries (dedup on trader + clientOrderId). cursor is the continuation point for the next step.
curl "http://127.0.0.1:8090/api/v1/markets/mkt-0001/orders/<orderId>?minCursor=<cursor>" \
-H "Authorization: Bearer $PMJ_TOKEN"
# → 200 {status: "OPEN"|"PARTIAL"|"FILLED"|"CANCELLED", filledE2, …}
# → 404 = the projection has not caught up, or the order does not exist (indistinguishable) — retry with the same cursor; the first 404 is not a terminal stateRead-your-writes: the projection trailing by a few milliseconds is normal. Terminal-state rules and cancel semantics live on the individual endpoint pages.
| State | Meaning |
|---|---|
202 accepted | Command persisted to the log, not yet matched. |
OPEN | Resting on the book, unfilled. |
PARTIAL | Partially filled, remainder still resting. |
FILLED | Fully filled (terminal). |
CANCELLED | Cancelled by you or by the system (heartbeat timeout, expiry) (terminal). |
SETTLING | Fill is in the settlement job ledger, executing on-chain. Seller proceeds sit in fillReserved. |
CONFIRMED | On-chain settlement confirmed; in on-chain mode this always means the chain really settled it. |
Order state comes from GET /markets/{marketId}/orders/{orderId}; settlement state from GET /me/settlements.