Skip to main content
This guide will walk you through setting up the CLOB Client and placing your first order on Polymarket. By the end, you’ll have a working example that can fetch market data and execute trades.

Prerequisites

Before you begin, make sure you have:
  • Node.js version 20.10 or higher
  • A Polygon wallet with a private key
  • Some USDC on Polygon (for trading) - get test USDC on Amoy testnet for development
  • Basic familiarity with TypeScript/JavaScript and async/await
Never commit your private key or API credentials to version control. Use environment variables or a secure secrets manager.

Installation

1

Install the package

Install the CLOB Client and ethers.js (or viem if you prefer):
npm install @polymarket/clob-client ethers@^5.8.0
The CLOB Client currently supports ethers v5.x. For viem, you can use viem v2.x.
2

Set up environment variables

Create a .env file in your project root:
.env
# Your Ethereum private key (without 0x prefix)
PK=your_private_key_here

# Chain ID: 137 for Polygon mainnet, 80002 for Amoy testnet
CHAIN_ID=80002

# CLOB API URL
CLOB_API_URL=https://clob.polymarket.com

# These will be generated in the next step
CLOB_API_KEY=
CLOB_SECRET=
CLOB_PASS_PHRASE=
3

Install dotenv for environment variables

npm install dotenv

Create API credentials

Before you can place orders, you need to create API credentials. These credentials are tied to your wallet address and allow the client to authenticate requests without signing every request with your wallet.
createApiKey.ts
import { ethers } from "ethers";
import { config as dotenvConfig } from "dotenv";
import { Chain, ClobClient } from "@polymarket/clob-client";

dotenvConfig();

async function main() {
    // Initialize wallet from private key
    const wallet = new ethers.Wallet(`${process.env.PK}`);
    const chainId = parseInt(`${process.env.CHAIN_ID || Chain.AMOY}`) as Chain;
    
    console.log(`Address: ${await wallet.getAddress()}, chainId: ${chainId}`);
    
    const host = process.env.CLOB_API_URL || "https://clob.polymarket.com";
    const clobClient = new ClobClient(host, chainId, wallet);
    
    // Create or derive API credentials
    // This uses createOrDeriveApiKey which will create new credentials
    // or return existing ones if they already exist for this wallet
    const apiCreds = await clobClient.createOrDeriveApiKey();
    
    console.log("API Credentials:");
    console.log(`CLOB_API_KEY=${apiCreds.key}`);
    console.log(`CLOB_SECRET=${apiCreds.secret}`);
    console.log(`CLOB_PASS_PHRASE=${apiCreds.passphrase}`);
    console.log("\nAdd these to your .env file");
}

main();
Run this script and save the output to your .env file:
npx tsx createApiKey.ts
The createOrDeriveApiKey() method is idempotent - it will return your existing credentials if you’ve already created them, or create new ones if you haven’t.

Fetch market data

Once you have your API credentials, you can start fetching market data. Here’s how to get market information and orderbook data:
getMarketData.ts
import { ethers } from "ethers";
import { config as dotenvConfig } from "dotenv";
import { Chain, ClobClient, ApiKeyCreds } from "@polymarket/clob-client";

dotenvConfig();

async function main() {
    const wallet = new ethers.Wallet(`${process.env.PK}`);
    const chainId = parseInt(`${process.env.CHAIN_ID || Chain.AMOY}`) as Chain;
    
    const host = process.env.CLOB_API_URL || "https://clob.polymarket.com";
    
    // Initialize client with API credentials
    const creds: ApiKeyCreds = {
        key: `${process.env.CLOB_API_KEY}`,
        secret: `${process.env.CLOB_SECRET}`,
        passphrase: `${process.env.CLOB_PASS_PHRASE}`,
    };
    
    const clobClient = new ClobClient(host, chainId, wallet, creds);
    
    // Get available markets (paginated)
    console.log("\nFetching markets...");
    const markets = await clobClient.getMarkets();
    console.log(`Found ${markets.count} markets`);
    console.log("First market:", markets.data[0]);
    
    // Get a specific market by condition ID
    // Replace with an actual condition ID from the markets response
    const conditionId = markets.data[0]?.condition_id;
    if (conditionId) {
        const market = await clobClient.getMarket(conditionId);
        console.log("\nMarket details:", market);
    }
    
    // Get orderbook for a specific token
    // Token IDs are the individual outcomes in a market
    const tokenId = markets.data[0]?.tokens?.[0]?.token_id;
    if (tokenId) {
        const orderbook = await clobClient.getOrderBook(tokenId);
        console.log("\nOrderbook:");
        console.log(`  Market: ${orderbook.market}`);
        console.log(`  Tick size: ${orderbook.tick_size}`);
        console.log(`  Best bid: ${orderbook.bids[0]?.price || 'none'}`);
        console.log(`  Best ask: ${orderbook.asks[0]?.price || 'none'}`);
        console.log(`  Last trade: ${orderbook.last_trade_price}`);
    }
}

main();

Place your first order

Now let’s create and post a limit order. This example places a buy order on a prediction market:
placeOrder.ts
import { ethers } from "ethers";
import { config as dotenvConfig } from "dotenv";
import { 
    Chain, 
    ClobClient, 
    ApiKeyCreds, 
    Side, 
    OrderType,
    SignatureType 
} from "@polymarket/clob-client";

dotenvConfig();

async function main() {
    const wallet = new ethers.Wallet(`${process.env.PK}`);
    const chainId = parseInt(`${process.env.CHAIN_ID || Chain.AMOY}`) as Chain;
    
    const host = process.env.CLOB_API_URL || "https://clob.polymarket.com";
    
    const creds: ApiKeyCreds = {
        key: `${process.env.CLOB_API_KEY}`,
        secret: `${process.env.CLOB_SECRET}`,
        passphrase: `${process.env.CLOB_PASS_PHRASE}`,
    };
    
    // SignatureType: 0 = EOA (MetaMask, etc), 1 = POLY_PROXY (email login), 2 = POLY_GNOSIS_SAFE
    const signatureType = SignatureType.EOA;
    
    // Funder address is your Polymarket profile address (where you deposit USDC)
    // For EOA wallets, this is typically the same as your wallet address
    const funderAddress = await wallet.getAddress();
    
    const clobClient = new ClobClient(
        host,
        chainId,
        wallet,
        creds,
        signatureType,
        funderAddress
    );
    
    // Replace with an actual token ID from a market you want to trade
    // You can get this from the getMarkets() or getMarket() response
    const tokenId = "YOUR_TOKEN_ID_HERE";
    
    console.log("\nCreating and posting order...");
    
    try {
        // Create and post a limit order in one step
        const orderResponse = await clobClient.createAndPostOrder(
            {
                tokenID: tokenId,
                price: 0.50,      // Price between 0 and 1 (represents probability)
                size: 10,         // Number of shares
                side: Side.BUY,   // BUY or SELL
            },
            {
                tickSize: "0.01", // Minimum price increment (get from market data)
                negRisk: false,   // Whether this is a neg-risk market (get from market data)
            },
            OrderType.GTC         // Good-til-canceled
        );
        
        console.log("Order posted successfully!");
        console.log("Order ID:", orderResponse.orderID);
        console.log("Status:", orderResponse.status);
        
        // Get order details
        if (orderResponse.orderID) {
            const orderDetails = await clobClient.getOrder(orderResponse.orderID);
            console.log("\nOrder details:", orderDetails);
        }
        
    } catch (error) {
        console.error("Error placing order:", error);
    }
}

main();
Prices on Polymarket are represented as probabilities between 0 and 1. A price of 0.50 means 50% probability, which costs $0.50 per share.

Place a market order

Market orders are filled immediately at the best available price. Here’s how to place a market buy order:
marketOrder.ts
import { ethers } from "ethers";
import { config as dotenvConfig } from "dotenv";
import { 
    Chain, 
    ClobClient, 
    ApiKeyCreds, 
    Side, 
    OrderType 
} from "@polymarket/clob-client";

dotenvConfig();

async function main() {
    const wallet = new ethers.Wallet(`${process.env.PK}`);
    const chainId = parseInt(`${process.env.CHAIN_ID || Chain.AMOY}`) as Chain;
    
    const host = process.env.CLOB_API_URL || "https://clob.polymarket.com";
    
    const creds: ApiKeyCreds = {
        key: `${process.env.CLOB_API_KEY}`,
        secret: `${process.env.CLOB_SECRET}`,
        passphrase: `${process.env.CLOB_PASS_PHRASE}`,
    };
    
    const clobClient = new ClobClient(host, chainId, wallet, creds);
    
    const tokenId = "YOUR_TOKEN_ID_HERE";
    
    console.log("\nPlacing market order...");
    
    try {
        // Create and post a market order
        // For BUY orders: amount is in USDC (dollars to spend)
        // For SELL orders: amount is in shares to sell
        const orderResponse = await clobClient.createAndPostMarketOrder(
            {
                tokenID: tokenId,
                amount: 100,        // $100 worth for BUY, or 100 shares for SELL
                side: Side.BUY,
                orderType: OrderType.FOK, // Fill-or-Kill (or use FAK for Fill-and-Kill)
            },
            {
                tickSize: "0.01",
            },
            OrderType.FOK
        );
        
        console.log("Market order executed!");
        console.log("Response:", orderResponse);
        
    } catch (error) {
        console.error("Error placing market order:", error);
    }
}

main();
Market orders support two types:
  • FOK (Fill-or-Kill): Order must be completely filled or it’s rejected
  • FAK (Fill-and-Kill): Order is partially filled and the rest is canceled

Check your orders and trades

Monitor your trading activity with these methods:
checkActivity.ts
import { ethers } from "ethers";
import { config as dotenvConfig } from "dotenv";
import { Chain, ClobClient, ApiKeyCreds } from "@polymarket/clob-client";

dotenvConfig();

async function main() {
    const wallet = new ethers.Wallet(`${process.env.PK}`);
    const chainId = parseInt(`${process.env.CHAIN_ID || Chain.AMOY}`) as Chain;
    
    const host = process.env.CLOB_API_URL || "https://clob.polymarket.com";
    
    const creds: ApiKeyCreds = {
        key: `${process.env.CLOB_API_KEY}`,
        secret: `${process.env.CLOB_SECRET}`,
        passphrase: `${process.env.CLOB_PASS_PHRASE}`,
    };
    
    const clobClient = new ClobClient(host, chainId, wallet, creds);
    
    // Get all open orders
    const openOrders = await clobClient.getOpenOrders();
    console.log(`\nYou have ${openOrders.length} open orders`);
    openOrders.forEach(order => {
        console.log(`  ${order.id}: ${order.side} ${order.original_size} @ ${order.price}`);
    });
    
    // Get recent trades
    const trades = await clobClient.getTrades({}, true); // true = only first page
    console.log(`\nRecent trades: ${trades.length}`);
    trades.slice(0, 5).forEach(trade => {
        console.log(`  ${trade.side} ${trade.size} @ ${trade.price} - ${trade.match_time}`);
    });
    
    // Cancel a specific order
    if (openOrders.length > 0) {
        const orderId = openOrders[0].id;
        console.log(`\nCanceling order ${orderId}...`);
        const cancelResponse = await clobClient.cancelOrder({ orderID: orderId });
        console.log("Canceled:", cancelResponse);
    }
    
    // Or cancel all orders
    // await clobClient.cancelAll();
}

main();

Next steps

API Reference

Explore all available methods and their parameters

Authentication

Learn more about L1 and L2 authentication

Order types

Understand different order types and when to use them

Error handling

Handle errors gracefully in your application

Common issues

Make sure your API credentials are correct and that you’re using the right chain ID. API credentials are chain-specific.
Each market has a minimum tick size. Fetch the market data first to get the correct tick size, or let the client fetch it automatically by not specifying tickSize in the options.
Make sure you have enough USDC in your wallet on Polygon. For testnet, get test USDC from a faucet.
For limit orders, if your price is too far from the market price, your order may not match immediately. Check the orderbook to see current prices. For market orders, there may not be enough liquidity at the current price level.

Build docs developers (and LLMs) love