PAPI
SDK

Exchanges

Polymarket and Kalshi specifics

Exchange Details

The SDK normalizes data across exchanges, but each exchange has unique characteristics you should understand.

Polymarket

Polymarket is a decentralized prediction market built on Polygon. PAPI uses two Polymarket APIs:

  • Gamma API — Market metadata, search, and discovery
  • CLOB API — Order book, trading, and positions

Market Status

Polymarket markets use boolean fields for status:

{
  "active": true,
  "closed": false
}
activeclosedMeaning
truefalseMarket is open for trading
falsefalseMarket is paused
falsetrueMarket is settled

Polymarket-Specific Fields

{
  "condition_id": "0xabc...",
  "question_id": "0xdef...",
  "tokens": [
    {
      "token_id": "12345",
      "outcome": "Yes",
      "price": "0.62",
      "winner": false
    }
  ],
  "rewards": {
    "min_size": 25,
    "max_spread": "0.04",
    "event_start_date": "2026-12-31T00:00:00Z"
  }
}

Token IDs

Polymarket markets have token IDs for each outcome. You need the token ID to place orders:

let market = client
    .market(Exchange::Polymarket, "market-slug-or-id")
    .send()
    .await?;

// Get the "Yes" token ID for trading
let yes_token = market.tokens.iter()
    .find(|t| t.outcome == "Yes")
    .expect("market has Yes outcome");

println!("Token ID: {}", yes_token.token_id);

Kalshi

Kalshi is a CFTC-regulated prediction market exchange. PAPI uses the Kalshi REST API.

Market Status

Kalshi uses string status values. The status field in responses is active, but query filtering uses open:

# Query for open markets
curl "https://api.papi.market/kalshi/markets?status=open" \
  -H "X-API-Key: <your-api-key>"
{
  "markets": [
    {
      "ticker": "KXBTC-26DEC31-T100000",
      "status": "active",
      "title": "Bitcoin above $100,000 on December 31?"
    }
  ]
}

Kalshi-Specific Fields

{
  "ticker": "KXBTC-26DEC31-T100000",
  "event_ticker": "KXBTC-26DEC31",
  "series_ticker": "KXBTC",
  "yes_bid": "0.62",
  "no_bid": "0.38",
  "yes_ask": "0.63",
  "no_ask": "0.37",
  "last_price": "0.62",
  "volume": 15420,
  "open_interest": 8350
}

Price Format

Kalshi natively uses cents (integer 0-100). The PAPI API converts these to decimals for consistency:

Kalshi RawPAPI Response
62"0.62"
5"0.05"
100"1.00"

All financial values in PAPI responses are strings to preserve decimal precision.

Unified Interface

Despite these differences, the SDK provides a consistent interface:

use papi_sdk::{PapiClient, Exchange};

let client = PapiClient::new(config);

// Same API for both exchanges
let poly_markets = client.markets(Exchange::Polymarket).send().await?;
let kalshi_markets = client.markets(Exchange::Kalshi).send().await?;

// Unified Market struct
for market in poly_markets.iter().chain(kalshi_markets.iter()) {
    println!("[{}] {} — {:?}", market.exchange, market.title, market.status);
}

On this page