polyoxide-data 0.17.0

Rust client library for Polymarket Data API
Documentation

polyoxide-data

Rust client library for the Polymarket Data API.

Read-only access to Polymarket user positions, trades, activity, holders, open interest, live volume, leaderboards, builder analytics, market-positions, and accounting snapshots. No authentication required.

More information about this crate can be found in the crate documentation.

Features

  • Read-Only, No Auth: All endpoints are public -- no API keys or signing needed
  • Fluent Builder Pattern: Chainable query parameters with .send().await?
  • Type-Safe Responses: Strongly-typed structs with serde deserialization
  • Built-In Rate Limiting: Automatic rate limiting and concurrency control (default: 4 concurrent requests)

Installation

[dependencies]
polyoxide-data = "0.17"

Or use the unified client:

[dependencies]
polyoxide = "0.17"

Usage

Create a Client

use polyoxide_data::DataApi;

# fn doctest() -> Result<(), Box<dyn std::error::Error>> {
// Default configuration
let data = DataApi::new()?;

// Or customize via the builder
let data = DataApi::builder()
    .timeout_ms(30_000)
    .pool_size(10)
    .max_concurrent(8)
    .build()?;
# let _ = data;
# Ok(())
# }

User Positions

# use polyoxide_data::DataApi;
use polyoxide_data::types::PositionSortBy;

# async fn doctest() -> Result<(), Box<dyn std::error::Error>> {
# let data = DataApi::builder().build()?;
let positions = data.user("0x1234...abcd")
    .list_positions()
    .limit(10)
    .sort_by(PositionSortBy::CashPnl)
    .send()
    .await?;

for pos in positions {
    println!("{}: size={} pnl={}", pos.title, pos.size, pos.cash_pnl);
}
# Ok(())
# }

User Position Value

# use polyoxide_data::DataApi;
# async fn doctest() -> Result<(), Box<dyn std::error::Error>> {
# let data = DataApi::builder().build()?;
let values = data.user("0x1234...abcd")
    .positions_value()
    .send()
    .await?;

for v in values {
    println!("Total value: {}", v.value);
}
# Ok(())
# }

Closed Positions

# use polyoxide_data::DataApi;
# async fn doctest() -> Result<(), Box<dyn std::error::Error>> {
# let data = DataApi::builder().build()?;
let closed = data.user("0x1234...abcd")
    .closed_positions()
    .limit(5)
    .send()
    .await?;

for pos in closed {
    println!("{}: realized P&L = {}", pos.title, pos.realized_pnl);
}
# Ok(())
# }

User Trades

# use polyoxide_data::DataApi;
use polyoxide_data::types::TradeSide;

# async fn doctest() -> Result<(), Box<dyn std::error::Error>> {
# let data = DataApi::builder().build()?;
let trades = data.user("0x1234...abcd")
    .trades()
    .side(TradeSide::Buy)
    .limit(20)
    .send()
    .await?;

for trade in trades {
    println!("{} {} @ {}", trade.title, trade.size, trade.price);
}
# Ok(())
# }

User Activity

# use polyoxide_data::DataApi;
use polyoxide_data::types::ActivityType;

# async fn doctest() -> Result<(), Box<dyn std::error::Error>> {
# let data = DataApi::builder().build()?;
let activity = data.user("0x1234...abcd")
    .activity()
    .activity_type([ActivityType::Trade, ActivityType::Redeem])
    .limit(50)
    .send()
    .await?;

for a in activity {
    println!("{:?}: {} USDC", a.activity_type, a.usdc_size);
}
# Ok(())
# }

Markets Traded Count

# use polyoxide_data::DataApi;
# async fn doctest() -> Result<(), Box<dyn std::error::Error>> {
# let data = DataApi::builder().build()?;
let traded = data.user("0x1234...abcd").traded().await?;
println!("Total markets traded: {}", traded.traded);
# Ok(())
# }

Global Trades

# use polyoxide_data::DataApi;
# async fn doctest() -> Result<(), Box<dyn std::error::Error>> {
# let data = DataApi::builder().build()?;
let trades = data.trades()
    .list()
    .limit(10)
    .send()
    .await?;

for trade in trades {
    println!("{}: {} @ {}", trade.title, trade.size, trade.price);
}
# Ok(())
# }

Top Holders

# use polyoxide_data::DataApi;
# async fn doctest() -> Result<(), Box<dyn std::error::Error>> {
# let data = DataApi::builder().build()?;
let holders = data.holders()
    .list(["condition_id_1", "condition_id_2"])
    .limit(50)
    .min_balance(100)
    .send()
    .await?;

for market in holders {
    println!("Token {}: {} holders", market.token, market.holders.len());
}
# Ok(())
# }

Open Interest

# use polyoxide_data::DataApi;
# async fn doctest() -> Result<(), Box<dyn std::error::Error>> {
# let data = DataApi::builder().build()?;
let oi = data.open_interest()
    .get()
    .market(["condition_id_here"])
    .send()
    .await?;

for entry in oi {
    println!("{}: {}", entry.market, entry.value);
}
# Ok(())
# }

Live Volume

# use polyoxide_data::DataApi;
# async fn doctest() -> Result<(), Box<dyn std::error::Error>> {
# let data = DataApi::builder().build()?;
let volumes = data.live_volume().get(12345).await?;

for vol in volumes {
    println!("Total volume: {}", vol.total);
}
# Ok(())
# }

Trader Leaderboard

# use polyoxide_data::DataApi;
use polyoxide_data::api::leaderboard::{LeaderboardCategory, LeaderboardOrderBy};
use polyoxide_data::types::TimePeriod;

# async fn doctest() -> Result<(), Box<dyn std::error::Error>> {
# let data = DataApi::builder().build()?;
let rankings = data.leaderboard()
    .get()
    .category(LeaderboardCategory::Politics)
    .time_period(TimePeriod::Week)
    .order_by(LeaderboardOrderBy::Pnl)
    .limit(10)
    .send()
    .await?;

for trader in rankings {
    println!("#{} {} - PnL: {}", trader.rank, trader.proxy_wallet, trader.pnl);
}
# Ok(())
# }

Builder Leaderboard

# use polyoxide_data::DataApi;
use polyoxide_data::types::TimePeriod;

# async fn doctest() -> Result<(), Box<dyn std::error::Error>> {
# let data = DataApi::builder().build()?;
let rankings = data.builders()
    .leaderboard()
    .time_period(TimePeriod::Week)
    .limit(10)
    .send()
    .await?;

for b in rankings {
    println!("#{} {} - volume: {}", b.rank, b.builder, b.volume);
}
# Ok(())
# }

Builder Volume Time Series

# use polyoxide_data::DataApi;
use polyoxide_data::types::TimePeriod;

# async fn doctest() -> Result<(), Box<dyn std::error::Error>> {
# let data = DataApi::builder().build()?;
let volumes = data.builders()
    .volume()
    .time_period(TimePeriod::Month)
    .send()
    .await?;

for entry in volumes {
    println!("{}: {} - volume {}", entry.dt, entry.builder, entry.volume);
}
# Ok(())
# }

Health Check

# use polyoxide_data::DataApi;
# async fn doctest() -> Result<(), Box<dyn std::error::Error>> {
# let data = DataApi::builder().build()?;
let health = data.health().check().await?;
println!("Status: {}", health.data);

let latency = data.health().ping().await?;
println!("API latency: {}ms", latency.as_millis());
# Ok(())
# }

API Namespaces

Namespace Access Description
data.user(addr) .list_positions(), .positions_value(), .closed_positions(), .trades(), .activity(), .traded() Per-user positions, trades, and activity
data.trades() .list() Global trade history with filtering
data.holders() .list(markets) Top token holders per market
data.open_interest() .get() Market open interest
data.live_volume() .get(event_id) Real-time event volume
data.leaderboard() .get() Trader rankings by PnL or volume
data.builders() .leaderboard(), .volume() Builder analytics and rankings
data.market_positions() .list(market) Aggregated positions for a market
data.accounting() .snapshot(addr) Accounting snapshot (ZIP bytes)
data.health() .check(), .ping() API health and latency

License

Licensed under either of MIT or Apache-2.0 at your option.