String Numerics
All price, quantity, balance, and monetary values in the API are returned as strings, not floats or integers.Why Strings?
IEEE 754 floating-point arithmetic causes precision errors that are unacceptable in financial applications:Decimal type internally. By returning strings, we ensure zero precision loss from server to client.
How to Handle
Fields That Are Strings
Every numeric field in the API uses string encoding:Known exception: GET /markets/updown live_price.buy / live_price.sell
The legacy /markets/updown endpoint emits live_price.buy and
live_price.sell as floats, not strings — every other API surface
uses strings. Parse defensively:
Decimal(str(buy)) before any order math:
/v1/markets, /v1/markets/{id}, /v1/prices/batch, and
WS /v1/ws/prices paths all emit string prices today and aren’t
affected.
Polymarket-parity exceptions
A small number of endpoints emit numeric (JSONnumber) values instead
of strings, because the corresponding Polymarket endpoint has always
done so and bot SDKs ported from Polymarket type-narrow on
typeof === "number". The list is intentionally short:
For all OTHER price-bearing endpoints (
GET /v1/price, /v1/midpoint,
/v1/spread, /v1/last-trade-price, /v1/book, /v1/account/positions,
etc.) the string convention continues to hold.
GET /v1/price returns a string. Live Polymarket emits
GET /price as {"price": "0.28"} — a JSON string, matching the
wire most trading bots actually parse, and PolySimulator does the same.
Wrap the value with Decimal(resp["price"]) or float(resp["price"])
to be robust. The quote_at (ISO string) and age_ms (int) freshness
fields accompany the price.Next Steps
- CLOB Compatibility — Polymarket API migration path
- Placing Orders — Use string numerics in practice