OCaml client library for the Polymarket prediction market API.
- Full coverage of the Polymarket Data API, Gamma API, and CLOB API
- Real-time WebSocket streaming for market data and user events
- L1 (EIP-712 wallet signing) and L2 (HMAC-SHA256) authentication for CLOB API
- Type-safe interface with validated primitive types and OCaml variant types
- Built on Eio for efficient concurrent I/O
- Pure-OCaml TLS for cross-platform compatibility (via tls-eio)
- Built-in rate limiting with official Polymarket API limits (GCRA algorithm)
- Type-safe HTTP request builder with phantom types
- Comprehensive error handling with result types
- JSON serialization via ppx_yojson_conv
- Pretty printing and equality functions for all types
- OCaml >= 5.1
- Dune >= 3.16
opam install polymarketOr add to your dune-project:
(depends
(polymarket (>= 0.1.0)))open Polymarket
let () =
(* Initialize RNG for TLS *)
Mirage_crypto_rng_unix.use_default ();
Eio_main.run @@ fun env ->
Eio.Switch.run @@ fun sw ->
let net = Eio.Stdenv.net env in
let clock = Eio.Stdenv.clock env in
(* Create a shared rate limiter with Polymarket presets *)
let rate_limiter = Rate_limiter.create_polymarket ~clock () in
(* Create a client *)
let client = Gamma.create ~sw ~net ~rate_limiter () in
(* Get active markets *)
match Gamma.get_markets client ~active:true ~limit:(Nonneg_int.of_int_exn 10) () with
| Ok markets ->
List.iter (fun (m : Gamma.market) ->
print_endline (Option.value ~default:"(no question)" m.question)
) markets
| Error err ->
print_endline ("Error: " ^ err.Http.error)The library uses validated primitive types like Address.t, Hash64.t, Limit.t, and Nonneg_int.t for type safety. Create them with *.of_int_exn, *.make_exn, or handle errors with *.of_int, *.make.
open Polymarket
let user_address = Address.make_exn "0x1a9a6f917a87a4f02c33f8530c6a8998f1bc8d59" in
match Data.get_positions client
~user:user_address
~limit:(Limit.of_int_exn 10)
~sort_by:Data.Position_sort_by.Cashpnl
~sort_direction:Data.Sort_direction.Desc
()
with
| Ok positions ->
List.iter (fun pos ->
Printf.printf "Position: %s, PnL: %s\n"
(Option.value ~default:"(unknown)" pos.title)
(Option.map string_of_float pos.cash_pnl
|> Option.value ~default:"N/A")
) positions
| Error err ->
Printf.printf "Error: %s\n" err.Http.errormatch Data.get_trades client
~user:user_address
~side:Data.Side.Buy
~limit:(Nonneg_int.of_int_exn 20)
()
with
| Ok trades ->
List.iter (fun trade ->
Printf.printf "Trade: %s @ %f\n"
(Option.value ~default:"(unknown)" trade.title)
(Option.value ~default:0.0 trade.price)
) trades
| Error err ->
Printf.printf "Error: %s\n" err.Http.errormatch Data.get_trader_leaderboard client
~category:Data.Leaderboard_category.Politics
~time_period:Data.Time_period.Week
~order_by:Data.Leaderboard_order_by.Pnl
~limit:(Leaderboard_limit.of_int_exn 10)
()
with
| Ok leaders ->
List.iter (fun entry ->
Printf.printf "#%s: %s - PnL: %f\n"
(Option.value ~default:"?" entry.rank)
(Option.value ~default:"(anonymous)" entry.user_name)
(Option.value ~default:0.0 entry.pnl)
) leaders
| Error err ->
Printf.printf "Error: %s\n" err.Http.errorThe Gamma API provides access to markets, events, series, and search functionality.
let rate_limiter = Rate_limiter.create_polymarket ~clock () in
let client = Gamma.create ~sw ~net ~rate_limiter () in
match Gamma.get_markets client ~active:true ~limit:(Nonneg_int.of_int_exn 10) () with
| Ok markets ->
List.iter (fun (m : Gamma.market) ->
Printf.printf "Market: %s\n"
(Option.value ~default:"(no question)" m.question)
) markets
| Error err ->
Printf.printf "Error: %s\n" err.Http.errormatch Gamma.get_events client ~tag_slug:"politics" ~limit:(Nonneg_int.of_int_exn 10) () with
| Ok events ->
List.iter (fun (e : Gamma.event) ->
Printf.printf "Event: %s\n"
(Option.value ~default:"(no title)" e.title)
) events
| Error err ->
Printf.printf "Error: %s\n" err.Http.errormatch Gamma.public_search client ~q:"election" ~limit_per_type:5 () with
| Ok search ->
let event_count = match search.events with Some e -> List.length e | None -> 0 in
Printf.printf "Found %d events\n" event_count
| Error err ->
Printf.printf "Error: %s\n" err.Http.errorThe CLOB (Central Limit Order Book) API provides access to order books, pricing, and authenticated trading endpoints.
The CLOB client uses a typestate pattern to enforce authentication requirements at compile time. Three client types exist:
Clob.Unauthed.t: Public endpoints only (order book, pricing, timeseries)Clob.L1.t: L1 wallet authentication (create/derive API keys) + publicClob.L2.t: L2 API key authentication (orders, trades) + L1 + public
open Polymarket
(* Start with an unauthenticated client for public data *)
let client = Clob.Unauthed.create ~sw ~net ~rate_limiter () in
(* Get order book - works on Unauthed client *)
match Clob.Unauthed.get_order_book client ~token_id () with
| Ok book -> Printf.printf "Bids: %d, Asks: %d\n"
(List.length book.bids) (List.length book.asks)
| Error err -> Printf.printf "Error: %s\n" err.Http.error
(* Upgrade to L1 with private key *)
let l1_client = Clob.upgrade_to_l1 client ~private_key in
Printf.printf "Address: %s\n" (Clob.L1.address l1_client);
(* Derive API credentials and auto-upgrade to L2 *)
match Clob.L1.derive_api_key l1_client ~nonce:0 with
| Ok (l2_client, _resp) ->
(* L2 client can access authenticated endpoints *)
let _ = Clob.L2.get_orders l2_client () in
let _ = Clob.L2.get_trades l2_client () in
(* L2 can also call public endpoints *)
let _ = Clob.L2.get_midpoint l2_client ~token_id () in
()
| Error err -> Printf.printf "Error: %s\n" err.Http.error(* Upgrade functions *)
val Clob.upgrade_to_l1 : unauthed -> private_key:string -> l1
val Clob.upgrade_to_l2 : l1 -> credentials:Auth.credentials -> l2
val Clob.L1.derive_api_key : l1 -> nonce:int -> (l2 * response, error) result
(* Downgrade functions *)
val Clob.l2_to_l1 : l2 -> l1
val Clob.l2_to_unauthed : l2 -> unauthed
val Clob.l1_to_unauthed : l1 -> unauthedlet rate_limiter = Rate_limiter.create_polymarket ~clock () in
let client = Clob.Unauthed.create ~sw ~net ~rate_limiter () in
let token_id = "12345..." in (* Token ID from Gamma API *)
match Clob.Unauthed.get_order_book client ~token_id () with
| Ok book ->
Printf.printf "Bids: %d, Asks: %d\n"
(List.length book.bids) (List.length book.asks)
| Error err ->
Printf.printf "Error: %s\n" err.Http.error(* Get price for a specific side *)
match Clob.Unauthed.get_price client ~token_id ~side:Clob.Types.Side.Buy () with
| Ok price -> Printf.printf "Price: %s\n" (Option.value ~default:"N/A" price.price)
| Error err -> Printf.printf "Error: %s\n" err.Http.error
(* Get midpoint price *)
match Clob.Unauthed.get_midpoint client ~token_id () with
| Ok mid -> Printf.printf "Midpoint: %s\n" (Option.value ~default:"N/A" mid.mid)
| Error err -> Printf.printf "Error: %s\n" err.Http.errorOnce you have an L2 client, you can access trading endpoints:
(* Get your open orders *)
match Clob.L2.get_orders l2_client () with
| Ok orders ->
List.iter (fun order ->
Printf.printf "Order: %s @ %s\n"
(Option.value ~default:"" order.id)
(Option.value ~default:"" order.price)
) orders
| Error err ->
Printf.printf "Error: %s\n" err.Http.error
(* Cancel all orders *)
match Clob.L2.cancel_all l2_client () with
| Ok resp -> Printf.printf "Cancelled: %d orders\n" (List.length resp.canceled)
| Error err -> Printf.printf "Error: %s\n" err.Http.errorThe library provides real-time WebSocket streaming for market data and user events using pure-OCaml TLS (tls-eio) for cross-platform compatibility.
Subscribe to orderbook updates for specific asset IDs:
open Polymarket
let () =
Mirage_crypto_rng_unix.use_default ();
Eio_main.run @@ fun env ->
Eio.Switch.run @@ fun sw ->
let net = Eio.Stdenv.net env in
let clock = Eio.Stdenv.clock env in
(* Get token IDs from Gamma API *)
let asset_ids = ["token_id_1"; "token_id_2"] in
(* Connect to market channel *)
let client = Wss.Market.connect ~sw ~net ~clock ~asset_ids () in
let stream = Wss.Market.stream client in
(* Process messages *)
let rec loop () =
match Eio.Stream.take stream with
| Wss.Types.Market (Book book) ->
Printf.printf "Book: %s - %d bids, %d asks\n"
book.asset_id (List.length book.bids) (List.length book.asks);
loop ()
| Wss.Types.Market (Price_change change) ->
Printf.printf "Price change: %d updates\n"
(List.length change.price_changes);
loop ()
| Wss.Types.Market (Last_trade_price trade) ->
Printf.printf "Trade: %s @ %s\n" trade.asset_id trade.price;
loop ()
| _ -> loop ()
in
loop ()Subscribe to your trades and orders with API credentials:
let credentials = Clob.Auth.{
api_key = "...";
secret = "...";
passphrase = "...";
} in
let markets = ["condition_id_1"; "condition_id_2"] in
let client = Wss.User.connect ~sw ~net ~clock ~credentials ~markets () in
let stream = Wss.User.stream client in
match Eio.Stream.take stream with
| Wss.Types.User (Trade trade) ->
Printf.printf "Trade: %s @ %s\n" trade.id trade.price
| Wss.Types.User (Order order) ->
Printf.printf "Order: %s %s @ %s\n" order.id order.side order.price
| _ -> ()Add or remove asset subscriptions on the fly:
(* Subscribe to additional assets *)
Wss.Market.subscribe client ~asset_ids:["new_token_id"];
(* Unsubscribe from assets *)
Wss.Market.unsubscribe client ~asset_ids:["old_token_id"];
(* Close connection *)
Wss.Market.close client| Channel | Message Type | Description |
|---|---|---|
| Market | Book |
Full orderbook snapshot |
| Market | Price_change |
Incremental orderbook update |
| Market | Last_trade_price |
Last trade price update |
| Market | Best_bid_ask |
Best bid/ask update |
| Market | Tick_size_change |
Tick size change notification |
| User | Trade |
Trade execution notification |
| User | Order |
Order status update |
The library includes built-in rate limiting that matches the official Polymarket API rate limits. A shared rate limiter enforces limits across all API clients.
Create a single rate limiter and share it across all clients to properly enforce global rate limits:
open Polymarket
Eio_main.run @@ fun env ->
Eio.Switch.run @@ fun sw ->
let net = Eio.Stdenv.net env in
let clock = Eio.Stdenv.clock env in
(* Create a shared rate limiter with Polymarket presets *)
let rate_limiter = Rate_limiter.create_polymarket ~clock () in
(* Share the same rate limiter across all clients *)
let gamma_client = Gamma.create ~sw ~net ~rate_limiter () in
let data_client = Data.create ~sw ~net ~rate_limiter () in
let clob_client = Clob.create ~sw ~net ~rate_limiter () in
(* All clients now share rate limit state *)When a rate limit is exceeded, the client can either delay (sleep) until the request can proceed, or return an error immediately. The default behavior is Delay, which is recommended for Cloudflare-protected APIs.
open Polymarket
(* Default: Delay behavior (sleeps until request can proceed) *)
let rate_limiter = Rate_limiter.create_polymarket ~clock () in
(* Or explicitly specify Error behavior *)
let rate_limiter = Rate_limiter.create_polymarket ~clock ~behavior:Rate_limiter.Error () inThe library includes pre-configured limits for all Polymarket APIs:
| API | General Limit | Notable Endpoint Limits |
|---|---|---|
| Data API | 1000/10s | /trades: 200/10s, /positions: 150/10s |
| Gamma API | 4000/10s | /events: 300/10s, /markets: 300/10s |
| CLOB API | 9000/10s | Trading endpoints with burst + sustained limits |
| Global | 15000/10s | Applies across all APIs |
The library provides a type-safe request builder with phantom types that enforce correct usage at compile time. The builder is used internally by all API modules and is also available for direct use when building custom requests.
Note: The builder is accessed via Polymarket_http.Builder. The high-level API modules (Polymarket.Gamma, Polymarket.Data, etc.) use the builder internally, so most users won't need to use it directly.
GETandDELETErequests are ready to execute immediatelyPOSTrequests require a body viawith_bodybefore execution- Authentication can be added via
with_l1_authorwith_l2_auth
open Polymarket_http.Builder
(* GET request with query parameters *)
let positions =
new_get client "/positions"
|> query_param "user" address
|> query_option "limit" string_of_int (Some 10)
|> fetch_json_list position_of_yojson
(* POST request - requires body before execution *)
let order =
new_post client "/order"
|> with_body order_json (* Changes not_ready -> ready *)
|> fetch_json order_of_yojson
(* DELETE request *)
let result =
new_delete client "/order"
|> query_param "id" order_id
|> fetch_unit| Function | Description |
|---|---|
query_param key value |
Add a required string parameter |
query_add key opt |
Add an optional string parameter |
query_option key to_string opt |
Add optional param with converter |
query_list key to_string opts |
Join list values with commas |
query_bool key opt |
Add boolean as "true"/"false" |
query_each key to_string opts |
Add each value as separate param |
(* L1 wallet authentication for API key creation *)
new_post client "/auth/api-key"
|> with_l1_auth ~private_key ~address ~nonce:0
|> with_body ""
|> fetch_json api_key_response_of_yojson
(* L2 API key authentication for trading - call after with_body for POST *)
new_post client "/order"
|> with_body order_json
|> with_l2_auth ~credentials ~address
|> fetch_json order_of_yojson
(* L2 auth for GET/DELETE *)
new_get client "/data/orders"
|> with_l2_auth ~credentials ~address
|> fetch_json_list order_of_yojson| Function | Description |
|---|---|
fetch |
Raw (status, body) for custom handling |
fetch_json parser |
Parse response as JSON object |
fetch_json_list parser |
Parse response as JSON array |
fetch_text |
Return body as string |
fetch_unit |
Discard body, succeed on 200/201/204 |
The phantom types prevent common errors:
(* This won't compile - POST needs a body *)
let _ = new_post client "/order" |> fetch_json parser
(* Error: This expression has type not_ready t
but was expected of type ready t *)
(* This compiles - body provided *)
let _ = new_post client "/order" |> with_body "{}" |> fetch_json parserThe library provides a flattened API through these main modules:
Polymarket
├── Gamma (* Markets, events, series, search *)
├── Data (* Positions, trades, activity, leaderboards *)
├── Clob (* Order books, pricing, trading *)
│ ├── Unauthed (* Public endpoints client *)
│ ├── L1 (* Wallet auth client *)
│ ├── L2 (* API key auth client *)
│ ├── Types (* order_side, order_type, time_interval, etc. *)
│ ├── Auth (* L1/L2 authentication *)
│ └── Crypto (* Signing and hashing *)
├── Wss (* Real-time WebSocket streaming *)
│ ├── Market (* Public market data channel *)
│ ├── User (* Authenticated user channel *)
│ └── Types (* Message types *)
├── Http (* HTTP client - alias for Polymarket_http.Client *)
├── Rate_limiter (* Rate limiting with GCRA algorithm *)
├── Auth (* Authentication types and header builders *)
├── Crypto (* Cryptographic utilities *)
└── Primitives (* Validated types: Address, Hash64, Limit, etc. *)
Polymarket_http (* Direct access to HTTP client components *)
├── Client (* HTTP client with TLS and rate limiting *)
├── Builder (* Type-safe request builder with phantom types *)
└── Json (* JSON parsing utilities *)
| Endpoint | Function | Description |
|---|---|---|
GET /health |
health_check |
Check API health status |
GET /positions |
get_positions |
Get current positions for a user |
GET /positions/closed |
get_closed_positions |
Get closed positions for a user |
GET /trades |
get_trades |
Get trades for a user or markets |
GET /activity |
get_activity |
Get on-chain activity for a user |
GET /holders |
get_holders |
Get top holders for markets |
GET /traded |
get_traded |
Get total markets a user has traded |
GET /value |
get_value |
Get total value of user positions |
GET /open-interest |
get_open_interest |
Get open interest for markets |
GET /live-volume |
get_live_volume |
Get live volume for an event |
GET /leaderboard/builder |
get_builder_leaderboard |
Get builder leaderboard |
GET /leaderboard/builder/volume |
get_builder_volume |
Get builder volume time-series |
GET /leaderboard/trader |
get_trader_leaderboard |
Get trader leaderboard |
| Endpoint | Function | Description |
|---|---|---|
GET /status |
status |
Check API health status |
GET /teams |
get_teams |
Get list of sports teams |
GET /teams/{id} |
get_team |
Get a team by ID |
GET /tags |
get_tags |
Get list of tags |
GET /tags/{id} |
get_tag |
Get a tag by ID |
GET /tags/slug/{slug} |
get_tag_by_slug |
Get a tag by slug |
GET /tags/{id}/related |
get_related_tags |
Get related tags |
GET /events |
get_events |
Get list of events |
GET /events/{id} |
get_event |
Get an event by ID |
GET /events/slug/{slug} |
get_event_by_slug |
Get an event by slug |
GET /events/{id}/tags |
get_event_tags |
Get tags for an event |
GET /markets |
get_markets |
Get list of markets |
GET /markets/{id} |
get_market |
Get a market by ID |
GET /markets/slug/{slug} |
get_market_by_slug |
Get a market by slug |
GET /markets/{id}/tags |
get_market_tags |
Get tags for a market |
GET /markets/{id}/description |
get_market_description |
Get market description |
GET /series |
get_series_list |
Get list of series |
GET /series/{id} |
get_series |
Get a series by ID |
GET /series/{id}/summary |
get_series_summary |
Get series summary |
GET /comments |
get_comments |
Get list of comments |
GET /comments/{id} |
get_comment |
Get a comment by ID |
GET /comments/user/{address} |
get_user_comments |
Get comments by user |
GET /profiles/public/{address} |
get_public_profile |
Get public profile |
GET /profiles/{address} |
get_profile |
Get profile by address |
GET /sports |
get_sports |
Get list of sports |
GET /sports/market-types |
get_sports_market_types |
Get sports market types |
GET /search |
public_search |
Search events, tags, profiles |
| Endpoint | Function | Description |
|---|---|---|
GET /book |
get_order_book |
Get order book for a token |
POST /books |
get_order_books |
Get order books for multiple tokens |
GET /price |
get_price |
Get price for a token and side |
GET /midpoint |
get_midpoint |
Get midpoint price for a token |
POST /prices |
get_prices |
Get prices for multiple tokens |
POST /spreads |
get_spreads |
Get spreads for multiple tokens |
GET /prices-history |
get_price_history |
Get price history for a market |
| Endpoint | Function | Description |
|---|---|---|
POST /auth/api-key |
create_api_key |
Create new API credentials |
GET /auth/derive-api-key |
derive_api_key |
Derive API credentials from wallet |
| Endpoint | Function | Description |
|---|---|---|
POST /order |
create_order |
Submit a new order |
POST /orders |
create_orders |
Submit multiple orders |
GET /data/order/{id} |
get_order |
Get order by ID |
GET /data/orders |
get_orders |
Get open orders |
DELETE /order |
cancel_order |
Cancel an order |
DELETE /orders |
cancel_orders |
Cancel multiple orders |
DELETE /cancel-all |
cancel_all |
Cancel all orders |
DELETE /cancel-market-orders |
cancel_market_orders |
Cancel orders for a market |
GET /data/trades |
get_trades |
Get trade history |
| Type | Description | Creation |
|---|---|---|
Address.t |
Ethereum address (0x + 40 hex chars) | Address.make_exn "0x..." |
Hash64.t |
64-character hex hash | Hash64.make_exn "0x..." |
Hash.t |
Variable-length hex string | Hash.make_exn "0x..." |
Nonneg_int.t |
Non-negative integer | Nonneg_int.of_int_exn 5 |
Pos_int.t |
Positive integer | Pos_int.of_int_exn 1 |
Limit.t |
Pagination limit (1-1000) | Limit.of_int_exn 100 |
Offset.t |
Pagination offset (0-10000) | Offset.of_int_exn 0 |
Timestamp.t |
Unix timestamp | Timestamp.of_float_exn 1234567890.0 |
| Module | Type | Values |
|---|---|---|
Data.Side |
t |
Buy, Sell |
Data.Activity_type |
t |
Trade, Split, Merge, Redeem, Reward, Conversion |
Data.Sort_direction |
t |
Asc, Desc |
Data.Time_period |
t |
Day, Week, Month, All |
Data.Leaderboard_category |
t |
Overall, Politics, Sports, Crypto, Culture, Mentions, Weather, Economics, Tech, Finance |
Data.Position_sort_by |
t |
Current, Initial, Tokens, Cashpnl, Percentpnl, Title, Resolving, Price, Avgprice |
| Module | Type | Values |
|---|---|---|
Gamma.Status |
t |
Active, Closed, All |
Gamma.Slug_size |
t |
Sm, Md, Lg |
Gamma.Parent_entity_type |
t |
Event, Series, Market |
| Module | Type | Values |
|---|---|---|
Clob.Types.Side |
t |
Buy, Sell |
Clob.Types.Order_type |
t |
Gtc, Gtd, Fok |
Clob.Types.Time_interval |
t |
Max, One_week, One_day, Six_hours, One_hour |
For finer-grained control, you can depend on individual sub-libraries:
| Library | Description |
|---|---|
polymarket |
Main library with flattened API (recommended) |
polymarket.common |
Shared primitives (Address, Hash64, etc.) and utilities |
polymarket.http |
HTTP client with TLS support, type-safe request builder |
polymarket.rate_limiter |
GCRA-based rate limiter (used internally by http) |
polymarket.gamma |
Gamma API client only |
polymarket.data |
Data API client only |
polymarket.clob |
CLOB API client only |
polymarket.wss |
WebSocket client with pure-OCaml TLS (via tls-eio) |
To use a sub-library, add it to your dune file:
(executable
(name my_app)
(libraries polymarket.gamma polymarket.common))# Install dependencies
opam install . --deps-only --with-test
# Build the project
dune build
# Build documentation
dune build @doc# Run all tests
dune runtest
# Run tests with verbose output
dune runtest --force --verbose# Data API demo
dune exec examples/data_api_demo.exe
# Gamma API demo
dune exec examples/gamma_api_demo.exe
# CLOB API demo
dune exec examples/clob_api_demo.exe
# CLOB API demo with private key for authentication
POLY_PRIVATE_KEY=your_private_key_hex dune exec examples/clob_api_demo.exe
# WebSocket streaming demo
dune exec examples/wss_demo.exedune fmtpolymarket/
├── lib/
│ ├── common/ # Shared utilities
│ │ ├── primitives.ml # Validated types (Address, Hash64, Limit, etc.)
│ │ ├── auth.ml # L1/L2 authentication header builders
│ │ ├── crypto.ml # Signing and hashing utilities
│ │ └── logger.ml # Structured logging
│ ├── http_client/ # HTTP client
│ │ ├── client.ml # TLS-enabled HTTP requests with rate limiting
│ │ ├── builder.ml # Type-safe request builder with phantom types
│ │ └── json.ml # JSON parsing utilities
│ ├── rate_limiter/ # GCRA-based rate limiter
│ │ ├── rate_limiter.ml # Main rate limiter module
│ │ ├── presets.ml # Polymarket API rate limit configs
│ │ ├── gcra.ml # Generic Cell Rate Algorithm
│ │ ├── state.ml # Thread-safe state management
│ │ ├── matcher.ml # Route matching logic
│ │ └── builder.ml # Route configuration builder
│ ├── data_api/ # Data API implementation
│ │ ├── endpoints.ml # API endpoint implementations
│ │ └── types.ml # Response types and enums
│ ├── gamma_api/ # Gamma API implementation
│ │ ├── endpoints.ml # API endpoint implementations
│ │ └── types.ml # Types and module-based enums
│ ├── clob_api/ # CLOB API implementation
│ │ ├── client.ml # Typestate client (compile-time auth)
│ │ ├── endpoints.ml # API endpoint implementations
│ │ ├── order_builder.ml # Order construction utilities
│ │ └── types.ml # Types and module-based enums
│ ├── websocket_client/ # WebSocket streaming client
│ │ ├── client.ml # Market and User channel clients
│ │ ├── connection.ml # Connection management with reconnect
│ │ ├── frame.ml # WebSocket frame encoding/decoding
│ │ ├── handshake.ml # HTTP upgrade handshake
│ │ └── types.ml # Message types
│ ├── polymarket.ml # Main module (flattened API)
│ └── polymarket.mli # Public interface
├── examples/
│ ├── data_api_demo.ml # Data API live demo
│ ├── gamma_api_demo.ml # Gamma API live demo
│ ├── clob_api_demo.ml # CLOB API live demo
│ ├── wss_demo.ml # WebSocket streaming demo
│ └── logger.ml # Demo logging utilities
├── test/ # Test suite
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
└── SECURITY.md
- API Reference - Generated OCaml documentation
- Polymarket API Docs - Official Polymarket documentation
- CONTRIBUTING.md - Contribution guidelines
- CHANGELOG.md - Version history
- SECURITY.md - Security policy
MIT - see LICENSE for details.