Package Exports
- @polybased/sdk
Readme
Polybased SDK
Polybased SDK is a comprehensive TypeScript toolkit for building on Polymarket — the world's largest prediction market platform.
Access real-time market data, historical trading information, WebSocket streams, and trading capabilities (scaffold) — all aligned with the official Polymarket Builder documentation.
✨ Features
- 🚀 Market Data — Fetch active markets with pagination support
- 📊 Data API — Historical trades, positions, holders, and activity (no auth required)
- 🔄 Real-time Streams — WebSocket orderbook with auto-reconnect & heartbeat
- 🛡️ Resilient — Built-in retry logic, rate limit handling, exponential backoff
- 🔒 Type-safe — Full TypeScript support with comprehensive type definitions
- 🪶 Lightweight — Minimal dependencies, optimized for performance
- 🎯 Developer-friendly — Intuitive API with detailed examples
- 🔐 Security-first — Clear guidance on private key handling and signing servers
- 🤖 AI-ready — Perfect for building trading bots and AI agents
📦 Installation
Option 1: Install from npm
npm install @polybased/sdkOption 2: Install from GitHub
npm install git+https://github.com/olliegrimes123/polybased-sdk.gitOption 3: Install from tarball (specific release)
npm install https://github.com/olliegrimes123/polybased-sdk/releases/download/v0.2.0-beta.0/polybased-sdk-0.2.0-beta.0.tgzRequirements
- Node.js >= 18.0.0
- TypeScript (optional, but recommended)
wspackage (required for WebSocket in Node.js)
npm install ws🌐 Endpoints
The SDK uses the official Polymarket API endpoints by default:
| Service | Default URL | Purpose |
|---|---|---|
| CLOB API | https://clob.polymarket.com |
Orderbook and trading operations |
| Data API | https://data-api.polymarket.com |
Historical data (no auth) |
| Gamma API | https://gamma-api.polymarket.com |
Market metadata |
| WebSocket | wss://ws-subscriptions-clob.polymarket.com/ws |
Real-time market streams |
Override Endpoints (optional)
const sdk = new PolybasedSDK({
endpoints: {
clobApi: "https://custom-clob.example.com",
dataApi: "https://custom-data.example.com",
gammaApi: "https://custom-gamma.example.com",
websocket: "wss://custom-ws.example.com/ws"
}
});🚀 Quickstart — Choose Your Path
Path 1: Data (No Authentication)
Access historical trades, positions, holders, and activity without any authentication.
import { PolybasedSDK } from "@polybased/sdk";
const sdk = new PolybasedSDK();
// Get recent trades
const { items: trades, nextCursor } = await sdk.data.getTrades({
limit: 50
});
console.log(`Found ${trades.length} trades`);
trades.forEach(trade => {
console.log(`${trade.side} ${trade.size} @ $${trade.price}`);
});
// Get user positions
const { items: positions } = await sdk.data.getPositions({
address: "0xYourAddress"
});
// Get market holders
const { items: holders } = await sdk.data.getHolders({
marketId: "0xMarketId"
});
// Get user activity
const { items: activity } = await sdk.data.getActivity({
address: "0xYourAddress",
from: "2024-01-01",
to: "2024-12-31"
});Path 2: Markets & Pagination
Fetch market metadata with built-in pagination support.
import { PolybasedSDK } from "@polybased/sdk";
const sdk = new PolybasedSDK();
// Get markets (single page)
const markets = await sdk.markets.getMarkets({
status: "open",
limit: 100
});
console.log(`Found ${markets.length} markets`);
// Iterate through all markets (automatic pagination)
for await (const marketPage of sdk.markets.iterMarkets({ status: "open" })) {
console.log(`Processing ${marketPage.length} markets...`);
// Process each page...
}
// Get a specific market
const market = await sdk.markets.getMarket("market-id");
console.log(market.question);
console.log(`Volume: $${market.volumeUsd}`);Path 3: Real-time Streams (WebSocket)
Subscribe to live orderbook updates with auto-reconnect and heartbeat.
⚠️ Important for Node.js: You must install and configure the ws package:
npm install wsimport { PolybasedSDK } from "@polybased/sdk";
// In Node.js, enable WebSocket support
if (typeof window === "undefined") {
globalThis.WebSocket = (await import("ws")).default as any;
}
const sdk = new PolybasedSDK({ debug: true });
// Subscribe to market orderbook
const unsubscribe = sdk.ws.onMarket(
"market-id",
(update) => {
if (update.type === "snapshot") {
const { bids, asks } = update.data;
console.log(`Best bid: $${bids[0]?.price.toFixed(4)}`);
console.log(`Best ask: $${asks[0]?.price.toFixed(4)}`);
} else {
console.log("Delta update received");
}
},
{
onOpen: () => console.log("Connected"),
onClose: () => console.log("Disconnected"),
onError: (err) => console.error("Error:", err),
onReconnect: (event) => {
console.log(`Reconnecting (attempt ${event.attempt})...`);
}
}
);
// Later: stop streaming
// unsubscribe();Path 4: Trading (Scaffold)
⚠️ SECURITY WARNING: Trading functionality is currently a scaffold. Full implementation requires @polymarket/clob-client integration.
NEVER expose private keys in browser/frontend code! Use a Builder Signing Server for frontend applications.
import { PolybasedSDK } from "@polybased/sdk";
const sdk = new PolybasedSDK();
// Backend only (NEVER in browser!)
// const trading = sdk.trading.init({ signer: yourSigner });
// Frontend (recommended - use a signing server)
const trading = sdk.trading.init({
builderServerUrl: "https://your-signing-server.com"
});
// Place order (implementation coming in next release)
// const orderId = await trading.placeOrder({
// tokenId: "0x123...",
// side: "BUY",
// price: 0.65,
// size: 10
// });📖 API Reference
PolybasedSDK
Main SDK class for interacting with Polymarket.
Constructor
const sdk = new PolybasedSDK(config?: PolybasedConfig);Configuration Options:
interface PolybasedConfig {
/** API endpoints (optional overrides) */
endpoints?: {
clobApi?: string;
dataApi?: string;
gammaApi?: string;
websocket?: string;
};
/** Enable debug logging */
debug?: boolean;
/** HTTP retry configuration */
retry?: {
maxRetries?: number; // Default: 3
baseDelayMs?: number; // Default: 300
maxDelayMs?: number; // Default: 10000
};
/** WebSocket configuration */
ws?: {
heartbeatIntervalMs?: number; // Default: 30000
heartbeatTimeoutMs?: number; // Default: 10000
maxReconnectAttempts?: number; // Default: 0 (infinite)
reconnectBaseDelayMs?: number; // Default: 300
reconnectMaxDelayMs?: number; // Default: 30000
};
/** Builder configuration for order attribution (optional) */
builder?: {
signingServerUrl?: string; // Builder Signing Server URL (frontend)
key?: string; // Builder API Key (backend only!)
secret?: string; // Builder API Secret (backend only!)
passphrase?: string; // Builder API Passphrase (backend only!)
};
}Properties
sdk.endpoints
Get current endpoint configuration.
const endpoints = sdk.endpoints;
console.log(endpoints.dataApi); // "https://data-api.polymarket.com"sdk.data — Data API
Access historical data (no authentication required).
// Get trades
const { items, nextCursor } = await sdk.data.getTrades({
marketId?: string;
address?: string;
side?: "BUY" | "SELL";
from?: string | number; // ISO string or epoch ms
to?: string | number;
cursor?: string;
limit?: number; // Default: 100
});
// Get positions
const { items, nextCursor } = await sdk.data.getPositions({
address: string; // Required
marketId?: string;
eventId?: string;
cursor?: string;
limit?: number;
});
// Get holders
const { items, nextCursor } = await sdk.data.getHolders({
marketId: string; // Required
cursor?: string;
limit?: number;
});
// Get activity
const { items, nextCursor } = await sdk.data.getActivity({
address: string; // Required
type?: string;
side?: "BUY" | "SELL";
from?: string | number;
to?: string | number;
cursor?: string;
limit?: number;
});sdk.markets — Markets API
Access market metadata with pagination.
// Get markets (single page)
const markets = await sdk.markets.getMarkets({
status?: "open" | "closed" | "resolved";
page?: number;
limit?: number;
sort?: "volume" | "liquidity" | "createdAt";
tags?: string[];
});
// Get a single market
const market = await sdk.markets.getMarket(marketId: string);
// Iterate through all markets (async generator)
for await (const marketPage of sdk.markets.iterMarkets(filters?)) {
// Process each page...
}sdk.ws — WebSocket Streams
Subscribe to real-time market data.
const unsubscribe = sdk.ws.onMarket(
marketId: string,
onUpdate: (update: OrderbookUpdate) => void,
options?: {
onOpen?: () => void;
onClose?: () => void;
onError?: (error: any) => void;
onReconnect?: (event: WsReconnectEvent) => void;
onStateChange?: (state: WsConnectionState) => void;
}
);
// Later: unsubscribe()sdk.trading — Trading (Scaffold)
Initialize trading client (scaffold implementation).
const trading = sdk.trading.init(
options: { signer: any } | { builderServerUrl: string }
);Backward-Compatible Methods (Deprecated)
These methods are kept for backward compatibility but are deprecated:
// ⚠️ Deprecated: Use sdk.markets.getMarkets() instead
const markets = await sdk.getMarkets();
// ⚠️ Deprecated: Use sdk.markets.getMarket() instead
const market = await sdk.getMarket(marketId);
// ⚠️ Deprecated: Use sdk.ws.onMarket() instead
const unsubscribe = sdk.onOrderbook(marketId, callback, options);🔄 Rate Limits & Retry Logic
The SDK includes intelligent rate limit handling and retry logic:
Rate Limit Handling (HTTP 429)
- Automatically respects
Retry-Afterheader when present - Falls back to exponential backoff with jitter (base ~300ms, cap ~10s)
- Only retries idempotent GET requests
- Throws
RateLimitErrorafter all retries are exhausted
Exponential Backoff
- Base delay: 300ms (configurable)
- Max delay: 10s (configurable)
- Jitter: Random component added to prevent thundering herd
- Max retries: 3 (configurable)
Configuration
const sdk = new PolybasedSDK({
retry: {
maxRetries: 5,
baseDelayMs: 500,
maxDelayMs: 15000
}
});Error Handling
import { HttpError, RateLimitError } from "@polybased/sdk";
try {
const trades = await sdk.data.getTrades();
} catch (error) {
if (error instanceof RateLimitError) {
console.error(`Rate limited! Retry after ${error.retryAfter}s`);
} else if (error instanceof HttpError) {
console.error(`HTTP ${error.status}: ${error.message}`);
}
}🔐 Security Best Practices
Never Expose Private Keys in Browser
❌ NEVER do this in frontend code:
// DANGEROUS - DO NOT USE IN BROWSER!
const signer = new Wallet(privateKey);
const trading = sdk.trading.init({ signer });Use a Builder Signing Server
✅ Recommended for frontend applications:
// SAFE - Use a signing server
const trading = sdk.trading.init({
builderServerUrl: "https://your-signing-server.com"
});Private Key Storage
- Backend/Server: Store private keys in environment variables
- Never: Commit private keys to version control
- Never: Hardcode private keys in source code
- Never: Expose private keys to browser/frontend
👷 Builder Profile & Order Attribution
Polymarket Builders can earn revenue share by attributing orders to their platform using Builder API credentials.
What is a Builder Profile?
A Builder Profile gives you:
- Order Attribution — Earn revenue share from orders placed through your app
- Authenticated APIs — Access to user-specific WebSocket streams and trading endpoints
- Builder Credentials — API Key, Secret, and Passphrase for signing requests
Getting Your Builder Credentials
- Visit Polymarket Builder Portal
- Create a Builder Profile
- Generate your API credentials:
BUILDER_KEY— Your Builder API KeyBUILDER_SECRET— Your Builder API SecretBUILDER_PASSPHRASE— Your Builder API Passphrase
⚠️ SECURITY: These credentials are as sensitive as private keys!
Storing Builder Credentials
Create a .env file in your project root (backend/server only):
# .env (NEVER commit this file!)
BUILDER_KEY=your_builder_api_key
BUILDER_SECRET=your_builder_api_secret
BUILDER_PASSPHRASE=your_builder_passphrase
# For frontend apps, point to your signing server
BUILDER_SIGNING_URL=https://your-signing-server.comAdd .env to your .gitignore:
.env
.env.local
.env.*.localUsing Builder Config in SDK
Option 1: Signing Server (Frontend - Recommended)
Frontend apps should NEVER have direct access to Builder credentials.
Use a Builder Signing Server to securely generate attribution headers:
import { PolybasedSDK } from "@polybased/sdk";
const sdk = new PolybasedSDK({
builder: {
signingServerUrl: process.env.BUILDER_SIGNING_URL
}
});Option 2: Direct Credentials (Backend Only)
⚠️ BACKEND/SERVER ONLY - NEVER in browser!
import { PolybasedSDK } from "@polybased/sdk";
const sdk = new PolybasedSDK({
builder: {
key: process.env.BUILDER_KEY,
secret: process.env.BUILDER_SECRET,
passphrase: process.env.BUILDER_PASSPHRASE
}
});Order Attribution Flow
When a user places an order through your platform:
- User Signs Order — User signs the order with their wallet
- Builder Adds Attribution — Your Builder credentials add attribution headers
- Order Submitted — Order is sent to CLOB with both signatures
import { PolybasedSDK, getBuilderHeaders } from "@polybased/sdk";
const sdk = new PolybasedSDK({
builder: {
signingServerUrl: process.env.BUILDER_SIGNING_URL
}
});
// Get builder headers for attribution
const headers = await getBuilderHeaders(sdk.config.builder!);
// Place order with attribution
const orderId = await sdk.trading.init().placeOrder(
{
tokenId: "0x123...",
side: "BUY",
price: 0.65,
size: 10
},
{ headers } // Builder attribution headers
);Builder Header Helpers
The SDK provides helper functions for generating Builder attribution headers:
import {
getBuilderHeadersRemote, // Frontend (via signing server)
getBuilderHeadersLocal, // Backend (direct credentials)
getBuilderHeaders // Auto-select based on config
} from "@polybased/sdk";
// Frontend: Get headers from signing server
const headers = await getBuilderHeadersRemote("https://your-server.com");
// Backend: Get headers from credentials (NEVER in browser!)
const headers = await getBuilderHeadersLocal({
key: process.env.BUILDER_KEY!,
secret: process.env.BUILDER_SECRET!,
passphrase: process.env.BUILDER_PASSPHRASE!
});
// Auto: Use builder config
const headers = await getBuilderHeaders(builderConfig);User WebSocket Subscriptions (Authenticated)
Builder credentials are required for authenticated user-specific WebSocket subscriptions:
import { onUserEvents, getBuilderHeadersRemote } from "@polybased/sdk";
// Subscribe to user's orders and fills
const unsubscribe = onUserEvents(
wsUrl,
"0xUserWalletAddress",
(event) => {
if (event.type === 'order_created') {
console.log('New order:', event);
}
if (event.type === 'fill') {
console.log('Order filled:', event);
}
},
{
getHeaders: async () => await getBuilderHeadersRemote(
process.env.BUILDER_SIGNING_URL!
)
}
);Note: User WebSocket subscriptions are currently scaffolded and will be fully implemented in a future release.
Learn More
- Polymarket Trading Documentation
- Builder Signing Server Guide
- Builder Profile Setup
- Order Attribution
💻 Examples
The SDK includes comprehensive examples in the examples/ directory.
Running Examples
All examples are network-guarded. Set RUN_EXAMPLES=1 to execute:
# List markets with pagination
RUN_EXAMPLES=1 tsx examples/list-markets.ts
# Get historical trades
RUN_EXAMPLES=1 tsx examples/data-trades.ts
# Get user positions
ADDRESS=0xYourAddress RUN_EXAMPLES=1 tsx examples/data-positions.ts
# Get market holders
MARKET_ID=0xMarketId RUN_EXAMPLES=1 tsx examples/data-holders.ts
# Get user activity
ADDRESS=0xYourAddress RUN_EXAMPLES=1 tsx examples/data-activity.ts
# Stream orderbook (WebSocket)
MARKET_ID=market-id RUN_EXAMPLES=1 tsx examples/ws-market.ts
# Stream orderbook (legacy/deprecated method)
MARKET_ID=market-id RUN_EXAMPLES=1 tsx examples/live-orderbook.ts
# Trading scaffold (backend only!)
PRIVATE_KEY=0x... RUN_EXAMPLES=1 tsx examples/first-order.tsExample: Data API
import { PolybasedSDK } from "@polybased/sdk";
const sdk = new PolybasedSDK();
// Get recent trades
const { items: trades } = await sdk.data.getTrades({ limit: 10 });
console.log(`Found ${trades.length} trades`);Example: WebSocket Stream
import { PolybasedSDK } from "@polybased/sdk";
// Node.js: Enable WebSocket
if (typeof window === "undefined") {
globalThis.WebSocket = (await import("ws")).default as any;
}
const sdk = new PolybasedSDK();
const unsubscribe = sdk.ws.onMarket("market-id", (update) => {
if (update.type === "snapshot") {
console.log("Best bid:", update.data.bids[0]?.price);
console.log("Best ask:", update.data.asks[0]?.price);
}
});🛠️ Troubleshooting
WebSocket Not Connecting
Problem: WebSocket is not defined error in Node.js
Solution: Install and configure the ws package:
npm install ws// Add at the top of your file
if (typeof window === "undefined") {
globalThis.WebSocket = (await import("ws")).default as any;
}Rate Limit Errors
Problem: Getting 429 Too Many Requests errors
Solution:
- The SDK automatically handles rate limits with retries
- Adjust retry configuration if needed:
const sdk = new PolybasedSDK({
retry: {
maxRetries: 5,
baseDelayMs: 500,
maxDelayMs: 20000
}
});- Add delays between requests in your code
- Consider caching responses
TypeScript Errors
Problem: Module resolution errors
Solution: Ensure you're using Node.js >= 18 and have proper tsconfig.json:
{
"compilerOptions": {
"module": "NodeNext",
"moduleResolution": "NodeNext",
"target": "ES2022"
}
}WebSocket Disconnects
Problem: WebSocket keeps disconnecting
Solution:
- The SDK includes auto-reconnect with exponential backoff
- Adjust reconnect configuration:
const sdk = new PolybasedSDK({
ws: {
heartbeatIntervalMs: 30000,
heartbeatTimeoutMs: 10000,
maxReconnectAttempts: 0, // 0 = infinite
reconnectBaseDelayMs: 300,
reconnectMaxDelayMs: 30000
}
});🤝 Contributing
We welcome contributions! See CONTRIBUTING.md for guidelines.
🔗 Links
- Polymarket: https://polymarket.com
- Builder Docs: https://docs.polymarket.com/developers/builders/builder-intro
- npm Package: https://www.npmjs.com/package/@polybased/sdk
- GitHub: https://github.com/olliegrimes123/polybased-sdk
- Website: https://polybased.xyz
- X (Twitter): @polybasedxyz
💡 About Polybased
Polybased aims to become the go-to SDK and data layer for on-chain prediction markets, starting with Polymarket.
Roadmap
- ✅ Polymarket data integration
- ✅ Real-time orderbook streaming with auto-reconnect
- ✅ Data API (trades, positions, holders, activity)
- ✅ Resilient HTTP with rate limit handling
- ✅ Comprehensive TypeScript support
- 🔨 Trading execution layer (in progress)
- 📊 Historical & aggregated market data (planned)
- 🌐 Dashboard examples and starter kits (planned)
$POLYBASED Token
Native token launched on PumpFun (Solana)
Contract Address: 446tM6t3j5KngSsahHDeYzdJByGjnsBRQrBxV4wUpump
📄 License
This project is licensed under the MIT License.
🙏 Acknowledgments
Built with ❤️ by the Polybased team for the prediction market community.
Special thanks to Polymarket for providing the infrastructure and documentation that makes this SDK possible.
© 2025 Polybased — Building the prediction-market toolkit of the future.