Skip to main content
The unified TypeScript SDK gives you a consistent surface across Polymarket discovery, market data, trading, account data, and realtime streams.
The TypeScript SDK is currently in beta. We are keeping it in this beta phase while we address issues and harden the SDK before transitioning to a more stable release.

Quickstart

1

Install the Package

Install the SDK from your package manager.
pnpm add @polymarket/client@beta
2

Create a Public Client

Create an instance of the PublicClient.
import { createPublicClient } from "@polymarket/client";

const client = createPublicClient();
3

Fetch Markets

Fetch a page of markets to discover active trading opportunities.
const markets = client.listMarkets({
  closed: false,
  pageSize: 5,
});

const firstPage = await markets.firstPage();

for (const market of firstPage.items) {
  // market: Market
}

SDK Patterns

The SDK normalizes data across API seams and uses consistent patterns for pagination and typed error handling across public and authenticated workflows.

Typed Primitives

Common primitives such as IDs, decimal values, date/time strings, and EVM addresses are represented with explicit SDK types so integrations can avoid treating every value as a plain string.
type Market = {
  id: MarketId;
  conditionId: ConditionId | null;
  state: {
    startDate?: IsoDateTimeString | null;
    endDate?: IsoDateTimeString | null;
  };
  outcomes: {
    yes: {
      tokenId: TokenId | null;
      price: DecimalString | null;
    };
  };
  resolution: {
    resolvedBy: EvmAddress | null;
  };
  // …
};

Market and Event Data

Market and event responses use normalized field names and TypeScript shapes instead of service-specific response formats.
type Market = {
  id: MarketId;
  slug?: string | null;
  conditionId: ConditionId | null;
  question?: string | null;
  description?: string | null;
  category?: string | null;
  image?: string | null;
  icon?: string | null;
  state: MarketState;
  outcomes: MarketOutcomes;
  metrics: MarketMetrics;
  prices: MarketPrices;
  trading: MarketTrading;
  resolution: MarketResolution;
  rewards: MarketRewards;
  sports: MarketSportsMetadata;
  tags: MarketTag[];
  // …
};

Pagination

List methods return a consistent paginator interface across paginated endpoints. Use for await to iterate through pages.
const markets = client.listMarkets({
  closed: false,
  pageSize: 10,
});

for await (const page of markets) {
  // page.items: Market[]
}
You can also fetch the first page directly and resume later from a cursor.
const firstPage = await markets.firstPage();
// firstPage.items: Market[]

for await (const page of markets.from(firstPage.nextCursor)) {
  // page.items: Market[]
}

Error Handling

Each public action exposes a matching error guard. Use it to handle expected SDK errors and rethrow anything unexpected.
Error guards make exhaustive checks easier and help surface newly added SDK error cases during upgrades.
import { ListMarketsError } from "@polymarket/client";

try {
  const markets = client.listMarkets({
    closed: false,
    pageSize: 10,
  });

  const firstPage = await markets.firstPage();
  // firstPage.items: Market[]
} catch (error) {
  if (!ListMarketsError.isError(error)) {
    throw error;
  }

  switch (error.name) {
    case "RateLimitError":
      // Retry later.
      break;
    case "UserInputError":
      // Fix the request parameters.
      break;
    default:
    // …
  }
}

Market Data

Use market data methods to fetch market and event details, order books, current prices, historical prices, and batch quotes.
const market = await client.fetchMarket({
  url: "https://polymarket.com/market/eth-flipped-in-2026",
});

const market = await client.fetchMarket({
  slug: "eth-flipped-in-2026",
});

const market = await client.fetchMarket({
  id: "12345",
});
Then fetch related tags, order books, prices, and history.
const marketTags = await client.fetchMarketTags({
  id: market.id,
});

const eventTags = await client.fetchEventTags({
  id: event.id,
});

Discovery

Use discovery methods to browse events, markets, teams, tags, comments, sports metadata, and search results. The examples below show a few common entry points.
const events = client.listEvents({
  pageSize: 10,
});

for await (const page of events) {
  // page.items: Event[]
}

Realtime Streams

Subscribe through one SDK interface even when events are served by different websocket surfaces. The SDK routes each subscription spec to the right stream and merges the results into one stream.
const stream = await client.subscribe([
  {
    topic: "market",
    tokenIds: [market.outcomes.yes.tokenId!],
  },
  {
    topic: "prices.crypto.binance",
    symbols: ["btcusdt"],
  },
]);

for await (const event of stream) {
  // event:
  //   | MarketBookEvent
  //   | MarketPriceChangeEvent
  //   | MarketLastTradePriceEvent
  //   | MarketTickSizeChangeEvent
  //   | CryptoPricesBinanceEvent

  if (shouldStopStreaming()) {
    await stream.close();
  }
}

Authenticated Client

Create a secure client when you need wallet-scoped reads or trading. By default, createSecureClient uses the signer’s deterministic Deposit Wallet as the account wallet. The SDK deploys that wallet if needed during client creation. Pass wallet only when you want to authenticate an existing wallet, such as an existing Deposit Wallet, Poly Safe, Poly Proxy, or the signer address itself for EOA trading. The examples below pass wallet to make account selection explicit. Omit wallet to use the default Deposit Wallet flow.

Wallet Integrations

The SDK is intended to support a variety of wallet libraries. At launch, we support Viem, Privy, and Ethers v5. We will expand support for more libraries based on demand.
1

Install the Packages

Install the SDK and Viem wallet tools.
pnpm add @polymarket/client@beta viem
2

Create the Secure Client

Use the private-key helper, or adapt an existing viem wallet client.
import { createSecureClient } from "@polymarket/client";
import { privateKey } from "@polymarket/client/viem";

const secureClient = await createSecureClient({
  wallet: "YOUR_POLYMARKET_WALLET_ADDRESS",
  signer: privateKey(process.env.PRIVATE_KEY),
});

Trading Setup

Before placing orders, make sure the authenticated wallet is deployed and has the required trading approvals. createSecureClient resolves the signer’s deterministic Deposit Wallet by default and deploys it if needed.
1

Configure API Key Authorization

Configure API key authorization when the SDK needs to deploy a Deposit Wallet or submit approval transactions.
import { createSecureClient, relayerApiKey } from "@polymarket/client";

const secureClient = await createSecureClient({
  wallet: "YOUR_POLYMARKET_WALLET_ADDRESS",
  signer,
  apiKey: relayerApiKey({
    key: process.env.RELAYER_API_KEY!,
    address: process.env.RELAYER_API_KEY_ADDRESS!,
  }),
});
Builder API keys are supported for backwards compatibility with builders that still use them for wallet operations. They are not used for order attribution. Use builderCode on orders for attribution.
2

Set Up Trading Approvals

Then set up trading approvals.
await secureClient.setupTradingApprovals();
setupTradingApprovals() waits for the setup transaction internally and is idempotent. If the wallet already has the required approvals, it returns without submitting a transaction.

Trading

Use a secure client to create, sign, and submit orders. Limit orders specify the price and size you want to trade. Market orders execute against resting liquidity immediately. Order placement returns a discriminated response. Check response.ok before reading order details.

Place Orders

import { OrderSide } from "@polymarket/client";

const response = await secureClient.placeLimitOrder({
  tokenId: market.outcomes.yes.tokenId!,
  side: OrderSide.BUY,
  price: 0.52,
  size: 10,
});

if (response.ok) {
  // response.orderId: string
} else {
  // response.code: OrderResponseErrorCode
  // response.message: string
}

Create, Then Post

Create signed orders separately when you want to review, store, or batch them before submitting.
import { OrderSide } from "@polymarket/client";

const order = await secureClient.createLimitOrder({
  tokenId: market.outcomes.yes.tokenId!,
  side: OrderSide.BUY,
  price: 0.52,
  size: 10,
});

const response = await secureClient.postOrder(order);

if (response.ok) {
  // response.orderId: string
} else {
  // response.code: OrderResponseErrorCode
  // response.message: string
}

Position Lifecycle

Use position lifecycle methods to split collateral into outcome tokens, merge complete sets back into collateral, or redeem resolved positions. These examples assume you created a secure client and set up trading approvals as shown above.
const handle = await secureClient.splitPosition({
  conditionId: market.conditionId!,
  amount: 1n,
});

const outcome = await handle.wait();

// outcome.transactionHash: TxHash

Wallet Operations

Use wallet operation methods for direct token movements from the authenticated wallet. These examples assume you created a secure client as shown above.
const handle = await secureClient.transferErc20({
  amount: 1n,
  recipientAddress: "RECIPIENT_ADDRESS",
  tokenAddress: secureClient.environment.collateralToken,
});

const outcome = await handle.wait();

// outcome.transactionHash: TxHash

Order Management

Manage open orders for the authenticated wallet after placement. These examples assume orderId comes from an accepted order response.
const order = await secureClient.fetchOrder({
  orderId,
});

// order: OpenOrder

Rewards and Scoring

Use rewards methods to inspect active reward programs and scoring methods to check whether orders are eligible for scoring.
const rewards = client.listCurrentRewards();

for await (const page of rewards) {
  // page.items: CurrentReward[]
}

Account Data

Secure clients can read account-scoped data for the authenticated wallet.
const positions = secureClient.listPositions({
  market: [market.id], // Or market.conditionId
  pageSize: 10,
});

for await (const page of positions) {
  // page.items: Position[]
}

Authentication Sessions

Secure clients expose the API credentials created for the authenticated session. Store them securely if you want to reuse the session later without requiring a new authentication signature while the credentials remain valid.
const secureClient = await createSecureClient({
  wallet: "YOUR_POLYMARKET_WALLET_ADDRESS",
  signer,
});

await storage.set("polymarketCredentials", secureClient.credentials);

Changelog

0.1.0-beta.6

  • Point Combos RFQ endpoints at the production domains: combos-rfq-api.polymarket.com (REST) and combos-rfq-gateway-quoter.polymarket.com (quoter WebSocket).

0.1.0-beta.5

  • Added listComboMarkets for fetching the Combo market catalog with typed bindings and SDK-owned pagination. See Combos.
  • Parse RFQ quote rejections that use the SUBMISSION_WINDOW_CLOSED gateway error code.

0.1.0-beta.4

  • Added Combos support for multi-leg RFQ positions. See Combos.
  • Reject whitespace-only search queries and trim leading or trailing search input.
  • ConditionId is now deprecated in favor of CtfConditionId; existing ConditionId exports remain available as deprecated aliases.

0.1.0-beta.3

Secure client setup now defaults to the Deposit Wallet flow createSecureClient can now derive and use the signer’s deterministic Deposit Wallet when you omit wallet. If you already know which Polymarket wallet you want to use, keep passing wallet.
const secureClient = await createSecureClient({
-  wallet: "YOUR_POLYMARKET_WALLET_ADDRESS",
   signer,
});
If you want to keep account selection explicit, no change is required:
const secureClient = await createSecureClient({
  wallet: "YOUR_POLYMARKET_WALLET_ADDRESS",
  signer,
});
setupTradingApprovals() now waits internally You no longer need to wait on the returned handle. Call the method once before trading; it is safe to call again if approvals are already set.
-const handle = await secureClient.setupTradingApprovals();
-await handle.wait();
+await secureClient.setupTradingApprovals();
Gasless setup helpers are deprecated You no longer need to call isGaslessReady() or setupGaslessWallet() in the normal setup path. Create the secure client, then set up trading approvals.
-const ready = await secureClient.isGaslessReady();
-
-if (!ready) {
-  secureClient = await secureClient.setupGaslessWallet();
-}
-
 await secureClient.setupTradingApprovals();

0.1.0-beta.2

First beta release of the unified TypeScript SDK. Install the beta package with your package manager:
pnpm add @polymarket/client@beta