> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Migrate from Legacy SDKs to Unified SDKs

> Move an existing Polymarket integration to the unified SDKs.

Migrate from the previous CLOB, relayer, and builder-signing clients to the
unified SDK.

> [tab] TypeScript
>
> The examples below map previous client capabilities to
> `@polymarket/client`. The SDK also covers the Gamma API and Data API. Migrating
> direct Gamma and Data calls can simplify application code and give you
> normalized, typed models that work seamlessly with the SDK's trading and
> account workflows.
>
> ## Install the Unified SDK
>
> Remove the previous CLOB, relayer, and builder-signing packages used by your
> integration. Then install the unified SDK and your wallet library.
>
> ```bash npm theme={null}
> npm uninstall @polymarket/clob-client-v2 @polymarket/builder-relayer-client @polymarket/builder-signing-sdk
> npm install @polymarket/client@latest viem
> ```
>
> ```bash pnpm theme={null}
> pnpm remove @polymarket/clob-client-v2 @polymarket/builder-relayer-client @polymarket/builder-signing-sdk
> pnpm add @polymarket/client@latest viem
> ```
>
> ```bash Yarn theme={null}
> yarn remove @polymarket/clob-client-v2 @polymarket/builder-relayer-client @polymarket/builder-signing-sdk
> yarn add @polymarket/client@latest viem
> ```
>
> ```bash Bun theme={null}
> bun remove @polymarket/clob-client-v2 @polymarket/builder-relayer-client @polymarket/builder-signing-sdk
> bun add @polymarket/client@latest viem
> ```
>
> > [!NOTE]
> >
> > The unified SDK includes signer adapters for Viem, Privy, and Ethers v5, so
> > you can connect your wallet library without implementing CLOB-specific
> > signing. See [Wallet
> > Integrations](https://docs.polymarket.com/getting-started/typescript.md#wallet-integrations) for setup
> > examples.
>
> ## Client and Wallet Setup
>
> ### Create a Public Client
>
> `PublicClient` provides unauthenticated market discovery and data reads.
> `createPublicClient` uses production by default and does not require a host or
> chain ID.
>
> ```ts Before theme={null}
> import { ClobClient } from "@polymarket/clob-client-v2";
>
> const client = new ClobClient({
>   host: "https://clob.polymarket.com",
>   chain: 137,
> });
> ```
>
> ```ts After theme={null}
> import { createPublicClient } from "@polymarket/client";
>
> const client = createPublicClient();
> ```
>
> ### Create an Authenticated Client
>
> `SecureClient` adds authenticated trading, account, and wallet actions.
> `createSecureClient` derives or creates CLOB credentials, resolves the account
> wallet, and configures the correct signing flow.
>
> ```ts Before theme={null}
> import { ClobClient, SignatureTypeV2 } from "@polymarket/clob-client-v2";
>
> const tempClient = new ClobClient({
>   host: "https://clob.polymarket.com",
>   chain: 137,
>   signer,
> });
> const credentials = await tempClient.createOrDeriveApiKey();
>
> const client = new ClobClient({
>   host: "https://clob.polymarket.com",
>   chain: 137,
>   signer,
>   creds: credentials,
>   signatureType: SignatureTypeV2.POLY_1271,
>   funderAddress: process.env.POLYMARKET_WALLET_ADDRESS,
> });
> ```
>
> ```ts After theme={null}
> import { type ApiKeyCreds, createSecureClient } from "@polymarket/client";
> import { privateKey } from "@polymarket/client/viem";
>
> const client = await createSecureClient({
>   wallet: process.env.POLYMARKET_WALLET_ADDRESS,
>   signer: privateKey(process.env.POLYMARKET_PRIVATE_KEY),
> });
> ```
>
> Omit `wallet` to use the default Deposit Wallet flow.
>
> ### Resume With Existing Credentials
>
> Read credentials from an authenticated client, store them securely, and pass
> them to a new client to resume with the same API key. The signer and wallet must
> identify the account that owns the credentials.
>
> ```ts Before theme={null}
> import { ClobClient, SignatureTypeV2 } from "@polymarket/clob-client-v2";
>
> const credentials = client.creds;
> if (!credentials) throw new Error("Client has no credentials");
>
> // Store the credentials securely.
>
> const resumedClient = new ClobClient({
>   host: "https://clob.polymarket.com",
>   chain: 137,
>   signer,
>   creds: credentials,
>   signatureType: SignatureTypeV2.POLY_1271,
>   funderAddress: process.env.POLYMARKET_WALLET_ADDRESS,
> });
> ```
>
> ```ts After theme={null}
> import { createSecureClient } from "@polymarket/client";
> import { privateKey } from "@polymarket/client/viem";
>
> const credentials = client.credentials;
>
> // Store the credentials securely.
>
> const resumedClient = await createSecureClient({
>   wallet: process.env.POLYMARKET_WALLET_ADDRESS,
>   signer: privateKey(process.env.POLYMARKET_PRIVATE_KEY),
>   // Restore the type if loading from storage erased it.
>   credentials: credentials as ApiKeyCreds,
> });
> ```
>
> ### Revoke the Current API Key
>
> Ending authentication revokes the current API key, invalidates the
> `SecureClient`, and returns a `PublicClient`.
>
> ```ts Before theme={null}
> await client.deleteApiKey();
> ```
>
> ```ts After theme={null}
> const publicClient = await client.endAuthentication();
> ```
>
> ### Configure Builder API Keys
>
> `SecureClient` accepts Builder authorization for gasless wallet actions.
> Migrate local or remote Builder signing to the matching helper.
>
> **Local Builder API key**
>
> Keep local Builder credentials on the server. The Node.js entrypoint generates
> the required HMAC headers.
>
> ```ts Before theme={null}
> import { RelayClient } from "@polymarket/builder-relayer-client";
> import { BuilderConfig } from "@polymarket/builder-signing-sdk";
>
> const builderConfig = new BuilderConfig({
>   localBuilderCreds: {
>     key: process.env.POLYMARKET_BUILDER_API_KEY!,
>     secret: process.env.POLYMARKET_BUILDER_SECRET!,
>     passphrase: process.env.POLYMARKET_BUILDER_PASSPHRASE!,
>   },
> });
>
> const relayer = new RelayClient(
>   "https://relayer-v2.polymarket.com",
>   137,
>   walletClient,
>   builderConfig,
> );
> ```
>
> ```ts After theme={null}
> import { createSecureClient } from "@polymarket/client";
> import { builderApiKey } from "@polymarket/client/node";
> import { privateKey } from "@polymarket/client/viem";
>
> const client = await createSecureClient({
>   signer: privateKey(process.env.POLYMARKET_PRIVATE_KEY),
>   apiKey: builderApiKey({
>     key: process.env.POLYMARKET_BUILDER_API_KEY!,
>     secret: process.env.POLYMARKET_BUILDER_SECRET!,
>     passphrase: process.env.POLYMARKET_BUILDER_PASSPHRASE!,
>   }),
> });
> ```
>
> **Remote Builder Signing**
>
> Keep Builder credentials behind your signing endpoint. The client sends the
> same `{ method, path, body }` request and applies the same Builder headers, so
> the endpoint contract does not change.
>
> ```ts Before theme={null}
> import { RelayClient } from "@polymarket/builder-relayer-client";
> import { BuilderConfig } from "@polymarket/builder-signing-sdk";
>
> const builderConfig = new BuilderConfig({
>   remoteBuilderConfig: {
>     url: "https://example.com/api/builder/sign",
>     token: process.env.BUILDER_SIGNING_TOKEN,
>   },
> });
>
> const relayer = new RelayClient(
>   "https://relayer-v2.polymarket.com",
>   137,
>   walletClient,
>   builderConfig,
> );
> ```
>
> ```ts After theme={null}
> import { createSecureClient, remoteBuilderSigning } from "@polymarket/client";
>
> const client = await createSecureClient({
>   signer,
>   apiKey: remoteBuilderSigning({
>     url: "https://example.com/api/builder/sign",
>     headers: {
>       Authorization: `Bearer ${process.env.BUILDER_SIGNING_TOKEN}`,
>     },
>   }),
> });
> ```
>
> On the signing server, replace `BuilderConfig.generateBuilderHeaders` with
> `buildHmacSignature`. Keep your existing caller authentication and
> authorization around this handler.
>
> ```ts Before theme={null}
> import { BuilderConfig } from "@polymarket/builder-signing-sdk";
>
> const builderConfig = new BuilderConfig({
>   localBuilderCreds: {
>     key: process.env.POLYMARKET_BUILDER_API_KEY!,
>     secret: process.env.POLYMARKET_BUILDER_SECRET!,
>     passphrase: process.env.POLYMARKET_BUILDER_PASSPHRASE!,
>   },
> });
>
> export async function POST(request: Request): Promise<Response> {
>   const { body, method, path } = await request.json();
>   const headers = await builderConfig.generateBuilderHeaders(
>     method,
>     path,
>     body,
>   );
>
>   return Response.json(headers);
> }
> ```
>
> ```ts After theme={null}
> import { buildHmacSignature } from "@polymarket/client";
>
> export async function POST(request: Request): Promise<Response> {
>   const { body, method, path } = await request.json();
>   const timestamp = Math.floor(Date.now() / 1000);
>
>   return Response.json({
>     POLY_BUILDER_API_KEY: process.env.POLYMARKET_BUILDER_API_KEY!,
>     POLY_BUILDER_PASSPHRASE: process.env.POLYMARKET_BUILDER_PASSPHRASE!,
>     POLY_BUILDER_SIGNATURE: await buildHmacSignature(
>       process.env.POLYMARKET_BUILDER_SECRET!,
>       timestamp,
>       method,
>       path,
>       body,
>     ),
>     POLY_BUILDER_TIMESTAMP: `${timestamp}`,
>   });
> }
> ```
>
> ### Configure Relayer API Keys
>
> `SecureClient` configures Relayer API keys directly. Pass the key and its
> associated address to `relayerApiKey` when reconnecting an existing account.
>
> ```ts theme={null}
> import { createSecureClient, relayerApiKey } from "@polymarket/client";
> import { privateKey } from "@polymarket/client/viem";
>
> const client = await createSecureClient({
>   wallet: process.env.POLYMARKET_WALLET_ADDRESS,
>   signer: privateKey(process.env.POLYMARKET_PRIVATE_KEY),
>   apiKey: relayerApiKey({
>     key: process.env.POLYMARKET_RELAYER_API_KEY!,
>     address: process.env.POLYMARKET_RELAYER_API_KEY_ADDRESS!,
>   }),
> });
> ```
>
> ### Deploy a Deposit Wallet
>
> Creating a `SecureClient` without a `wallet` derives the signer's Deposit Wallet
> address and deploys it when needed. Use one of the Builder authorization
> strategies above to authorize the deployment.
>
> ```ts Before theme={null}
> const deployment = await relayer.deployDepositWallet();
> await deployment.wait();
> ```
>
> ```ts After theme={null}
> import { createSecureClient } from "@polymarket/client";
> import { builderApiKey } from "@polymarket/client/node";
> import { privateKey } from "@polymarket/client/viem";
>
> const client = await createSecureClient({
>   signer: privateKey(process.env.POLYMARKET_PRIVATE_KEY),
>   apiKey: builderApiKey({
>     key: process.env.POLYMARKET_BUILDER_API_KEY!,
>     secret: process.env.POLYMARKET_BUILDER_SECRET!,
>     passphrase: process.env.POLYMARKET_BUILDER_PASSPHRASE!,
>   }),
> });
>
> const depositWalletAddress = client.account.wallet;
> ```
>
> ## Market Discovery
>
> ### Fetch a Market
>
> Both `PublicClient` and `SecureClient` provide `fetchMarket` for reads by Gamma
> market ID, slug, or Polymarket URL.
>
> ```ts Before theme={null}
> const market = await client.getMarket("CONDITION_ID");
> ```
>
> ```ts After theme={null}
> const market = await client.fetchMarket({ slug: "MARKET_SLUG" });
> ```
>
> If you only have a condition ID, filter `listMarkets` and fetch its first page.
>
> ```ts theme={null}
> const page = await client
>   .listMarkets({ conditionIds: ["CONDITION_ID"] })
>   .firstPage();
>
> const market = page.items[0];
> ```
>
> ### List Markets
>
> Both `PublicClient` and `SecureClient` provide `listMarkets`, which returns a
> paginator and accepts filters directly.
>
> ```ts Before theme={null}
> const page = await client.getMarkets();
> const markets = page.data;
> ```
>
> ```ts After theme={null}
> const pages = client.listMarkets({ closed: false, pageSize: 20 });
> const page = await pages.firstPage();
> const markets = page.items;
> ```
>
> `getSimplifiedMarkets` does not need a separate replacement. Unified market
> models are normalized for SDK use. Sampling-market reads should migrate to
> `listCurrentRewards`, which lists the active reward configurations.
>
> ```ts Before theme={null}
> const markets = await client.getSamplingMarkets();
> const page = await client.getSamplingSimplifiedMarkets();
> ```
>
> ```ts After theme={null}
> const pages = client.listCurrentRewards();
> const page = await pages.firstPage();
> ```
>
> ## Market Data
>
> ### Read Trading Parameters
>
> Both `PublicClient` and `SecureClient` return tick size and negative-risk status
> on the unified market model. Order methods also resolve them automatically, so
> you no longer pass either value when placing an order.
>
> ```ts Before theme={null}
> const tickSize = await client.getTickSize("TOKEN_ID");
> const negRisk = await client.getNegRisk("TOKEN_ID");
> ```
>
> ```ts After theme={null}
> const market = await client.fetchMarket({ slug: "MARKET_SLUG" });
> const tickSize = market.trading.minimumTickSize;
> const negRisk = market.state.negRisk;
> ```
>
> ### Read CLOB Market Details
>
> Both `PublicClient` and `SecureClient` return the normalized market model for
> public product data. Its trading fields replace the compact CLOB market response
> and standalone fee reads.
>
> ```ts Before theme={null}
> const info = await client.getClobMarketInfo("CONDITION_ID");
> const feeRateBps = await client.getFeeRateBps("TOKEN_ID");
> const feeExponent = await client.getFeeExponent("TOKEN_ID");
> ```
>
> ```ts After theme={null}
> const page = await client
>   .listMarkets({ conditionIds: ["CONDITION_ID"] })
>   .firstPage();
>
> const market = page.items[0];
> const feeSchedule = market?.trading.feeSchedule;
> ```
>
> ### Fetch Order Books
>
> Both `PublicClient` and `SecureClient` provide single and batch order book reads
> with camelCase request fields.
>
> ```ts Before theme={null}
> const book = await client.getOrderBook("TOKEN_ID");
> const books = await client.getOrderBooks([
>   { token_id: "TOKEN_ID_1" },
>   { token_id: "TOKEN_ID_2" },
> ]);
> ```
>
> The unified SDK uses `assetId` for an outcome's trading identifier: a token ID
> for a CTF market or a position ID for a Polymarket Protocol V2 market. Use the
> identifier exposed for that outcome.
>
> ```ts After theme={null}
> const book = await client.fetchOrderBook({ assetId: "ASSET_ID" });
> const books = await client.fetchOrderBooks([
>   { assetId: "ASSET_ID_1" },
>   { assetId: "ASSET_ID_2" },
> ]);
> ```
>
> ### Fetch Prices
>
> Both `PublicClient` and `SecureClient` provide single and batch price reads with
> `OrderSide` and camelCase request fields.
>
> ```ts Before theme={null}
> import { Side } from "@polymarket/clob-client-v2";
>
> const price = await client.getPrice("TOKEN_ID", Side.BUY);
> const prices = await client.getPrices([
>   { token_id: "TOKEN_ID_1", side: Side.BUY },
>   { token_id: "TOKEN_ID_2", side: Side.SELL },
> ]);
> ```
>
> ```ts After theme={null}
> import { OrderSide } from "@polymarket/client";
>
> const price = await client.fetchPrice({
>   assetId: "ASSET_ID",
>   side: OrderSide.BUY,
> });
> const prices = await client.fetchPrices([
>   { assetId: "ASSET_ID_1", side: OrderSide.BUY },
>   { assetId: "ASSET_ID_2", side: OrderSide.SELL },
> ]);
> ```
>
> ### Fetch Midpoints
>
> Both `PublicClient` and `SecureClient` provide `fetchMidpoint` and
> `fetchMidpoints` for single and batch reads.
>
> ```ts Before theme={null}
> const midpoint = await client.getMidpoint("TOKEN_ID");
> const midpoints = await client.getMidpoints([
>   { token_id: "TOKEN_ID_1" },
>   { token_id: "TOKEN_ID_2" },
> ]);
> ```
>
> ```ts After theme={null}
> const midpoint = await client.fetchMidpoint({ assetId: "ASSET_ID" });
> const midpoints = await client.fetchMidpoints([
>   { assetId: "ASSET_ID_1" },
>   { assetId: "ASSET_ID_2" },
> ]);
> ```
>
> ### Fetch Spreads
>
> Both `PublicClient` and `SecureClient` provide single and batch spread reads
> with the same request pattern.
>
> ```ts Before theme={null}
> const spread = await client.getSpread("TOKEN_ID");
> const spreads = await client.getSpreads([
>   { token_id: "TOKEN_ID_1" },
>   { token_id: "TOKEN_ID_2" },
> ]);
> ```
>
> ```ts After theme={null}
> const spread = await client.fetchSpread({ assetId: "ASSET_ID" });
> const spreads = await client.fetchSpreads([
>   { assetId: "ASSET_ID_1" },
>   { assetId: "ASSET_ID_2" },
> ]);
> ```
>
> ### Fetch Last Trade Prices
>
> Both `PublicClient` and `SecureClient` provide singular and batch methods for
> last-trade prices.
>
> ```ts Before theme={null}
> const lastTrade = await client.getLastTradePrice("TOKEN_ID");
> const lastTrades = await client.getLastTradesPrices([
>   { token_id: "TOKEN_ID_1" },
>   { token_id: "TOKEN_ID_2" },
> ]);
> ```
>
> ```ts After theme={null}
> const lastTrade = await client.fetchLastTradePrice({ assetId: "ASSET_ID" });
> const lastTrades = await client.fetchLastTradePrices([
>   { assetId: "ASSET_ID_1" },
>   { assetId: "ASSET_ID_2" },
> ]);
> ```
>
> ### Fetch Price History
>
> Both `PublicClient` and `SecureClient` provide a price history paginator. Pass
> parameters in one request object; each page contains typed price history points.
>
> ```ts Before theme={null}
> const history = await client.getPricesHistory({
>   market: "TOKEN_ID",
>   interval: "1d",
>   fidelity: 60,
> });
> ```
>
> ```ts After theme={null}
> import { PriceHistoryInterval } from "@polymarket/client";
>
> const pages = client.listPriceHistory({
>   assetId: "ASSET_ID",
>   interval: PriceHistoryInterval.OneDay,
>   bucketSeconds: 3600,
> });
> const page = await pages.firstPage();
> const history = page.items;
> ```
>
> ### Estimate a Market Order Price
>
> Both `PublicClient` and `SecureClient` provide market-order price estimates. The
> request distinguishes collateral spent for buys from shares sold for sells.
>
> ```ts Before theme={null}
> const price = await client.calculateMarketPrice(
>   "TOKEN_ID",
>   Side.BUY,
>   100,
>   OrderType.FAK,
> );
> ```
>
> ```ts After theme={null}
> const price = await client.estimateMarketPrice({
>   assetId: "ASSET_ID",
>   side: OrderSide.BUY,
>   amount: 100,
> });
> ```
>
> ### List Recent Market Trades
>
> Both `PublicClient` and `SecureClient` provide the public trade paginator, which
> replaces the previous market-events response.
>
> ```ts Before theme={null}
> const trades = await client.getMarketTradesEvents("CONDITION_ID");
> ```
>
> ```ts After theme={null}
> const pages = client.listTrades({ conditionId: ["CONDITION_ID"] });
> const page = await pages.firstPage();
> const trades = page.items;
> ```
>
> ## Orders
>
> ### Place a Limit Order
>
> `SecureClient` resolves tick size, negative-risk status, fees, and signing
> details before it submits a limit order.
>
> ```ts Before theme={null}
> const response = await client.createAndPostOrder(
>   {
>     tokenID: "TOKEN_ID",
>     price: 0.52,
>     size: 10,
>     side: Side.BUY,
>   },
>   { tickSize: "0.01", negRisk: false },
>   OrderType.GTC,
> );
> ```
>
> ```ts After theme={null}
> const response = await client.placeLimitOrder({
>   assetId: "ASSET_ID",
>   price: 0.52,
>   size: 10,
>   side: OrderSide.BUY,
> });
> ```
>
> Set `expiration` for a GTD order and `postOnly: true` for a post-only order.
>
> ### Place a Market Order
>
> `SecureClient` places market orders. Buys specify collateral to spend, while
> sells specify shares to sell.
>
> ```ts Before theme={null}
> const response = await client.createAndPostMarketOrder(
>   {
>     tokenID: "TOKEN_ID",
>     amount: 10,
>     userUSDCBalance: 10,
>     side: Side.BUY,
>   },
>   { tickSize: "0.01", negRisk: false },
>   OrderType.FAK,
> );
> ```
>
> ```ts After theme={null}
> const response = await client.placeMarketOrder({
>   assetId: "ASSET_ID",
>   amount: 10,
>   maxSpend: 10,
>   side: OrderSide.BUY,
>   orderType: OrderType.FAK,
> });
> ```
>
> `userUSDCBalance` becomes `maxSpend`. The previous field supplied the account
> balance used to adjust the order for fees; the unified SDK instead accepts the
> maximum total USD to spend. Set `maxSpend` equal to `amount` when the amount
> should include fees, or omit it to pay applicable fees on top.
>
> ### Sign Without Posting
>
> `SecureClient` provides order-type-specific creation methods when signing and
> submission need to happen separately.
>
> ```ts Before theme={null}
> const signedOrder = await client.createOrder(
>   {
>     tokenID: "TOKEN_ID",
>     price: 0.52,
>     size: 10,
>     side: Side.BUY,
>   },
>   { tickSize: "0.01", negRisk: false },
> );
>
> const response = await client.postOrder(signedOrder, OrderType.GTC);
> ```
>
> ```ts After theme={null}
> const signedOrder = await client.createLimitOrder({
>   assetId: "ASSET_ID",
>   price: 0.52,
>   size: 10,
>   side: OrderSide.BUY,
> });
>
> const response = await client.postOrder(signedOrder);
> ```
>
> Use `createMarketOrder` instead when preparing an FAK or FOK market order.
>
> ### Post Several Orders
>
> `SecureClient` provides `postOrders`. Order type and post-only behavior are part
> of each signed order, so the method accepts the signed orders directly.
>
> ```ts Before theme={null}
> const response = await client.postOrders([
>   { order: firstOrder, orderType: OrderType.GTC },
>   { order: secondOrder, orderType: OrderType.GTC },
> ]);
> ```
>
> ```ts After theme={null}
> const response = await client.postOrders([firstOrder, secondOrder]);
> ```
>
> ### Attribute an Order to a Builder
>
> `SecureClient` attaches the builder code to each order.
>
> ```ts Before theme={null}
> const response = await client.createAndPostOrder(
>   {
>     tokenID: "TOKEN_ID",
>     price: 0.52,
>     size: 10,
>     side: Side.BUY,
>     builderCode: process.env.POLYMARKET_BUILDER_CODE,
>   },
>   { tickSize: "0.01", negRisk: false },
> );
> ```
>
> ```ts After theme={null}
> const response = await client.placeLimitOrder({
>   assetId: "ASSET_ID",
>   price: 0.52,
>   size: 10,
>   side: OrderSide.BUY,
>   builderCode: process.env.POLYMARKET_BUILDER_CODE,
> });
> ```
>
> ### Cancel Orders
>
> `SecureClient` provides the cancel methods. They now accept camelCase request
> objects, while `cancelAll` remains parameterless.
>
> ```ts Before theme={null}
> await client.cancelOrder("ORDER_ID");
> await client.cancelOrders(["ORDER_ID_1", "ORDER_ID_2"]);
> await client.cancelAll();
> await client.cancelMarketOrders({
>   market: "CONDITION_ID",
>   asset_id: "TOKEN_ID",
> });
> ```
>
> ```ts After theme={null}
> await client.cancelOrder({ orderId: "ORDER_ID" });
> await client.cancelOrders({ orderIds: ["ORDER_ID_1", "ORDER_ID_2"] });
> await client.cancelAll();
> await client.cancelMarketOrders({
>   market: "CONDITION_ID",
>   assetId: "ASSET_ID",
> });
> ```
>
> ### Fetch an Order
>
> `SecureClient` fetches an order by ID using a request object.
>
> ```ts Before theme={null}
> const order = await client.getOrder("ORDER_ID");
> ```
>
> ```ts After theme={null}
> const order = await client.fetchOrder({ orderId: "ORDER_ID" });
> ```
>
> ### List Open Orders
>
> `SecureClient` provides `listOpenOrders`, which returns a paginator. Filters and
> response fields use camelCase.
>
> ```ts Before theme={null}
> const orders = await client.getOpenOrders({
>   market: "CONDITION_ID",
>   asset_id: "TOKEN_ID",
> });
> ```
>
> ```ts After theme={null}
> const pages = client.listOpenOrders({
>   market: "CONDITION_ID",
>   assetId: "ASSET_ID",
> });
> const orders = [];
> for await (const page of pages) {
>   orders.push(...page.items);
> }
> ```
>
> ### Check Order Scoring
>
> `SecureClient` provides `fetchOrderScoring` for one order and
> `fetchOrdersScoring` for several.
>
> ```ts Before theme={null}
> const scoring = await client.isOrderScoring({ orderId: "ORDER_ID" });
> const batch = await client.areOrdersScoring({
>   orderIds: ["ORDER_ID_1", "ORDER_ID_2"],
> });
> ```
>
> ```ts After theme={null}
> const scoring = await client.fetchOrderScoring({ orderId: "ORDER_ID" });
> const batch = await client.fetchOrdersScoring({
>   orderIds: ["ORDER_ID_1", "ORDER_ID_2"],
> });
> ```
>
> ## Account Activity and Balances
>
> ### List Account Trades
>
> `SecureClient` replaces both previous account trade-history methods with one
> paginator.
>
> ```ts Before theme={null}
> const trades = await client.getTrades({ market: "CONDITION_ID" });
> const page = await client.getTradesPaginated({ market: "CONDITION_ID" });
> ```
>
> ```ts After theme={null}
> const pages = client.listAccountTrades({ market: "CONDITION_ID" });
> const firstPage = await pages.firstPage();
>
> const trades = [];
> for await (const page of pages) {
>   trades.push(...page.items);
> }
> ```
>
> ### List Builder Trades
>
> Both `PublicClient` and `SecureClient` provide public builder trade history,
> filtered by builder code.
>
> ```ts Before theme={null}
> const trades = await client.getBuilderTrades();
> ```
>
> ```ts After theme={null}
> const pages = client.listBuilderTrades({
>   builderCode: process.env.POLYMARKET_BUILDER_CODE,
> });
> const page = await pages.firstPage();
> const trades = page.items;
> ```
>
> ### Read and Drop Notifications
>
> `SecureClient` provides notification methods with action-oriented names and
> camelCase request fields.
>
> ```ts Before theme={null}
> const notifications = await client.getNotifications();
> await client.dropNotifications({ ids: [1, 2] });
> ```
>
> ```ts After theme={null}
> const notifications = await client.fetchNotifications();
> await client.dropNotifications({ ids: ["1", "2"] });
> ```
>
> ### Refresh Balances and Allowances
>
> `SecureClient` manages balances and allowances while placing orders. It detects
> a missing allowance, completes the required approval, refreshes the balance and
> allowance, and retries the order.
>
> ```ts Before theme={null}
> await client.updateBalanceAllowance({
>   asset_type: AssetType.COLLATERAL,
> });
>
> const balance = await client.getBalanceAllowance({
>   asset_type: AssetType.COLLATERAL,
> });
> ```
>
> ```ts After theme={null}
> const response = await client.placeLimitOrder({
>   assetId: "ASSET_ID",
>   price: 0.52,
>   size: 10,
>   side: OrderSide.BUY,
> });
> ```
>
> ## Positions
>
> The unified methods build and submit the wallet transactions. You no longer
> need to encode contract calls or pass transaction arrays to `execute`.
>
> ### Split a Position
>
> `SecureClient` splits collateral into a complete set of YES and NO outcome
> tokens.
>
> ```ts Before theme={null}
> const splitTx = {
>   to: CTF_COLLATERAL_ADAPTER_ADDRESS,
>   data: collateralAdapterInterface.encodeFunctionData("splitPosition", [
>     PUSD_ADDRESS,
>     ethers.constants.HashZero,
>     conditionId,
>     [1, 2],
>     ethers.utils.parseUnits("1", 6),
>   ]),
>   value: "0",
> };
>
> const split = await relayer.execute([splitTx], "Split position");
> await split.wait();
> ```
>
> ```ts After theme={null}
> const split = await client.splitPosition({
>   conditionId,
>   amount: 1_000_000n,
> });
>
> await split.wait();
> ```
>
> ### Merge Positions
>
> `SecureClient` merges balanced YES and NO tokens back into collateral.
>
> ```ts Before theme={null}
> const mergeTx = {
>   to: CTF_COLLATERAL_ADAPTER_ADDRESS,
>   data: collateralAdapterInterface.encodeFunctionData("mergePositions", [
>     PUSD_ADDRESS,
>     ethers.constants.HashZero,
>     conditionId,
>     [1, 2],
>     ethers.utils.parseUnits("1", 6),
>   ]),
>   value: "0",
> };
>
> const merge = await relayer.execute([mergeTx], "Merge positions");
> await merge.wait();
> ```
>
> ```ts After theme={null}
> const merge = await client.mergePositions({
>   conditionId,
>   amount: "max",
> });
>
> await merge.wait();
> ```
>
> ### Redeem Resolved Positions
>
> `SecureClient` redeems winning outcome tokens for collateral after resolution.
>
> ```ts Before theme={null}
> const redeemTx = {
>   to: CTF_COLLATERAL_ADAPTER_ADDRESS,
>   data: collateralAdapterInterface.encodeFunctionData("redeemPositions", [
>     PUSD_ADDRESS,
>     ethers.constants.HashZero,
>     conditionId,
>     [1, 2],
>   ]),
>   value: "0",
> };
>
> const redeem = await relayer.execute([redeemTx], "Redeem positions");
> await redeem.wait();
> ```
>
> ```ts After theme={null}
> const redeem = await client.redeemPositions({ conditionId });
> await redeem.wait();
> ```
>
> ## Service Status
>
> Neither `PublicClient` nor `SecureClient` requires these calls. The unified
> clients manage request timing internally.
>
> ```ts Before theme={null}
> await client.getOk();
> const timestamp = await client.getServerTime();
> ```
>
> ```ts After theme={null}
> // No client call is required for request timestamp synchronization.
> ```

> [tab] Python
>
> The examples below map previous client capabilities to `polymarket-client`.
> The SDK also covers the Gamma API and Data API. Migrating direct Gamma and
> Data calls can simplify application code and give you normalized, typed
> models that work seamlessly with the SDK's trading and account workflows.
>
> Public clients provide unauthenticated market discovery and data reads.
> Secure clients add authenticated trading, account, and wallet actions.
> Python provides async and sync versions of each, so choose the interface
> that matches your application's execution model.
>
> | Interface | Clients | Best for |
> | - | - | - |
> | Async | `AsyncPublicClient`, `AsyncSecureClient` | Services, bots, and applications using an event loop |
> | Sync | `PublicClient`, `SecureClient` | Scripts, notebooks, and synchronous applications |
>
> The examples below use the async clients.
>
> > [!NOTE]
> >
> > Some features are available only through the async clients due to their
> > streaming nature.
>
> ## Install the Unified SDK
>
> Remove the previous CLOB, relayer, and builder-signing packages. Then install the
> unified SDK.
>
> ```bash uv theme={null}
> uv remove py-clob-client-v2 py-builder-relayer-client py-builder-signing-sdk
> uv add polymarket-client
> ```
>
> ```bash pip theme={null}
> pip uninstall -y py-clob-client-v2 py-builder-relayer-client py-builder-signing-sdk
> pip install polymarket-client
> ```
>
> ```bash Poetry theme={null}
> poetry remove py-clob-client-v2 py-builder-relayer-client py-builder-signing-sdk
> poetry add polymarket-client
> ```
>
> ## Client and Wallet Setup
>
> ### Create a Public Client
>
> `AsyncPublicClient` provides unauthenticated market discovery and data reads.
> Production is the default environment.
>
> ```python Before theme={null}
> from py_clob_client_v2.client import ClobClient
>
> client = ClobClient("https://clob.polymarket.com", chain_id=137)
> ```
>
> ```python After theme={null}
> from polymarket import AsyncPublicClient
>
> client = AsyncPublicClient()
> ```
>
> ### Create an Authenticated Client
>
> `AsyncSecureClient` adds authenticated trading, account, and wallet actions.
> `create` derives or creates CLOB credentials, resolves the account wallet, and
> configures signing.
>
> ```python Before theme={null}
> import os
>
> from py_clob_client_v2.client import ClobClient
> from py_clob_client_v2.order_utils.model import SignatureTypeV2
>
> temporary_client = ClobClient(
>     "https://clob.polymarket.com",
>     chain_id=137,
>     key=os.environ["POLYMARKET_PRIVATE_KEY"],
> )
> credentials = temporary_client.create_or_derive_api_key()
>
> client = ClobClient(
>     "https://clob.polymarket.com",
>     chain_id=137,
>     key=os.environ["POLYMARKET_PRIVATE_KEY"],
>     creds=credentials,
>     signature_type=SignatureTypeV2.POLY_1271,
>     funder=os.environ["POLYMARKET_WALLET_ADDRESS"],
> )
> ```
>
> ```python After theme={null}
> import os
>
> from polymarket import AsyncSecureClient
>
> client = await AsyncSecureClient.create(
>     private_key=os.environ["POLYMARKET_PRIVATE_KEY"],
>     wallet=os.environ["POLYMARKET_WALLET_ADDRESS"],
> )
> ```
>
> Omit `wallet` to use the default Deposit Wallet flow.
>
> ### Resume With Existing Credentials
>
> Read credentials from an authenticated client, store them securely, and pass
> them to a new client to resume with the same API key. The private key and wallet
> must identify the account that owns the credentials.
>
> ```python Before theme={null}
> import os
>
> from py_clob_client_v2.client import ClobClient
> from py_clob_client_v2.order_utils.model import SignatureTypeV2
>
> credentials = client.creds
> if credentials is None:
>     raise RuntimeError("Client has no credentials")
>
> # Store the credentials securely.
>
> resumed_client = ClobClient(
>     "https://clob.polymarket.com",
>     chain_id=137,
>     key=os.environ["POLYMARKET_PRIVATE_KEY"],
>     creds=credentials,
>     signature_type=SignatureTypeV2.POLY_1271,
>     funder=os.environ["POLYMARKET_WALLET_ADDRESS"],
> )
> ```
>
> ```python After theme={null}
> import os
>
> from polymarket import AsyncSecureClient
>
> credentials = client.credentials
>
> # Store the credentials securely.
>
> resumed_client = await AsyncSecureClient.create(
>     private_key=os.environ["POLYMARKET_PRIVATE_KEY"],
>     wallet=os.environ["POLYMARKET_WALLET_ADDRESS"],
>     credentials=credentials,
> )
> ```
>
> ### Revoke the Current API Key
>
> Ending authentication revokes the current API key, invalidates the
> `AsyncSecureClient`, and returns an `AsyncPublicClient`.
>
> ```python Before theme={null}
> client.delete_api_key()
> ```
>
> ```python After theme={null}
> public_client = await client.end_authentication()
> ```
>
> ### Configure Builder API Keys
>
> `AsyncSecureClient` accepts a `BuilderApiKey` for gasless wallet actions. Keep
> the key, secret, and passphrase on the server.
>
> ```python Before theme={null}
> import os
>
> from py_builder_relayer_client.client import RelayClient
> from py_builder_signing_sdk.config import BuilderConfig
> from py_builder_signing_sdk.sdk_types import BuilderApiKeyCreds
>
> builder_config = BuilderConfig(
>     local_builder_creds=BuilderApiKeyCreds(
>         key=os.environ["POLYMARKET_BUILDER_API_KEY"],
>         secret=os.environ["POLYMARKET_BUILDER_SECRET"],
>         passphrase=os.environ["POLYMARKET_BUILDER_PASSPHRASE"],
>     )
> )
>
> relayer = RelayClient(
>     "https://relayer-v2.polymarket.com",
>     137,
>     os.environ["POLYMARKET_PRIVATE_KEY"],
>     builder_config,
> )
> ```
>
> ```python After theme={null}
> import os
>
> from polymarket import AsyncSecureClient, BuilderApiKey
>
> client = await AsyncSecureClient.create(
>     private_key=os.environ["POLYMARKET_PRIVATE_KEY"],
>     api_key=BuilderApiKey(
>         key=os.environ["POLYMARKET_BUILDER_API_KEY"],
>         secret=os.environ["POLYMARKET_BUILDER_SECRET"],
>         passphrase=os.environ["POLYMARKET_BUILDER_PASSPHRASE"],
>     ),
> )
> ```
>
> ### Configure Relayer API Keys
>
> `AsyncSecureClient` configures Relayer API keys directly. Pass the key and its
> associated address when reconnecting an existing account.
>
> ```python theme={null}
> import os
>
> from polymarket import AsyncSecureClient, RelayerApiKey
>
> client = await AsyncSecureClient.create(
>     private_key=os.environ["POLYMARKET_PRIVATE_KEY"],
>     wallet=os.environ["POLYMARKET_WALLET_ADDRESS"],
>     api_key=RelayerApiKey(
>         key=os.environ["POLYMARKET_RELAYER_API_KEY"],
>         address=os.environ["POLYMARKET_RELAYER_API_KEY_ADDRESS"],
>     ),
> )
> ```
>
> ### Deploy a Deposit Wallet
>
> Creating an `AsyncSecureClient` without a `wallet` derives the signer's Deposit
> Wallet address and deploys it when needed. Use Builder authorization to
> authorize the deployment.
>
> ```python Before theme={null}
> deployment = relayer.deploy_deposit_wallet()
> deployment.wait()
> ```
>
> ```python After theme={null}
> import os
>
> from polymarket import AsyncSecureClient, BuilderApiKey
>
> client = await AsyncSecureClient.create(
>     private_key=os.environ["POLYMARKET_PRIVATE_KEY"],
>     api_key=BuilderApiKey(
>         key=os.environ["POLYMARKET_BUILDER_API_KEY"],
>         secret=os.environ["POLYMARKET_BUILDER_SECRET"],
>         passphrase=os.environ["POLYMARKET_BUILDER_PASSPHRASE"],
>     ),
> )
>
> deposit_wallet_address = client.wallet
> ```
>
> ## Market Discovery
>
> ### Fetch a Market
>
> Both `AsyncPublicClient` and `AsyncSecureClient` provide `get_market` for reads
> by Gamma market ID, slug, or Polymarket URL.
>
> ```python Before theme={null}
> market = client.get_market("CONDITION_ID")
> ```
>
> ```python After theme={null}
> market = await client.get_market(slug="MARKET_SLUG")
> ```
>
> If you only have a condition ID, filter `list_markets` and fetch its first page.
>
> ```python theme={null}
> pages = client.list_markets(condition_ids=["CONDITION_ID"])
> page = await pages.first_page()
> market = page.items[0]
> ```
>
> ### List Markets
>
> Both `AsyncPublicClient` and `AsyncSecureClient` provide `list_markets`, which
> returns an async paginator and accepts filters directly.
>
> ```python Before theme={null}
> page = client.get_markets()
> markets = page["data"]
> ```
>
> ```python After theme={null}
> pages = client.list_markets(closed=False, page_size=20)
> page = await pages.first_page()
> markets = page.items
> ```
>
> Simplified-market reads do not need a separate replacement. Sampling-market
> reads migrate to `list_current_rewards`, which lists active reward
> configurations.
>
> ```python Before theme={null}
> markets = client.get_sampling_markets()
> page = client.get_sampling_simplified_markets()
> ```
>
> ```python After theme={null}
> pages = client.list_current_rewards()
> page = await pages.first_page()
> ```
>
> ## Market Data
>
> ### Read Trading Parameters
>
> Both `AsyncPublicClient` and `AsyncSecureClient` return tick size and
> negative-risk status on the market model. Order methods also resolve them
> automatically.
>
> ```python Before theme={null}
> tick_size = client.get_tick_size("TOKEN_ID")
> neg_risk = client.get_neg_risk("TOKEN_ID")
> fee_rate_bps = client.get_fee_rate_bps("TOKEN_ID")
> ```
>
> ```python After theme={null}
> market = await client.get_market(slug="MARKET_SLUG")
> tick_size = market.trading.minimum_tick_size
> neg_risk = market.state.neg_risk
> fee_schedule = market.trading.fee_schedule
> ```
>
> ### Read CLOB Market Details
>
> Both `AsyncPublicClient` and `AsyncSecureClient` return the typed market model.
> Its trading fields replace the compact CLOB market response.
>
> ```python Before theme={null}
> details = client.get_clob_market_info("CONDITION_ID")
> tick_size = details["mts"]
> neg_risk = details["nr"]
> fee_details = details["fd"]
> ```
>
> ```python After theme={null}
> market = await client.get_market(slug="MARKET_SLUG")
> tick_size = market.trading.minimum_tick_size
> neg_risk = market.state.neg_risk
> fee_schedule = market.trading.fee_schedule
> ```
>
> ### Fetch Order Books
>
> Both `AsyncPublicClient` and `AsyncSecureClient` provide single and batch order
> book reads.
>
> ```python Before theme={null}
> from py_clob_client_v2 import BookParams
>
> book = client.get_order_book("TOKEN_ID")
> books = client.get_order_books(
>     [BookParams(token_id="TOKEN_ID_1"), BookParams(token_id="TOKEN_ID_2")]
> )
> ```
>
> ```python After theme={null}
> book = await client.get_order_book(asset_id="ASSET_ID")
> books = await client.get_order_books(asset_ids=["ASSET_ID_1", "ASSET_ID_2"])
> ```
>
> ### Fetch Prices
>
> Both `AsyncPublicClient` and `AsyncSecureClient` provide single and batch price
> reads with typed requests.
>
> ```python Before theme={null}
> from py_clob_client_v2 import BookParams, Side
>
> price = client.get_price("TOKEN_ID", Side.BUY)
> prices = client.get_prices(
>     [
>         BookParams(token_id="TOKEN_ID_1", side=Side.BUY),
>         BookParams(token_id="TOKEN_ID_2", side=Side.SELL),
>     ]
> )
> ```
>
> ```python After theme={null}
> from polymarket import PriceRequest
>
> price = await client.get_price(asset_id="ASSET_ID", side="BUY")
> prices = await client.get_prices(
>     requests=[
>         PriceRequest(asset_id="ASSET_ID_1", side="BUY"),
>         PriceRequest(asset_id="ASSET_ID_2", side="SELL"),
>     ]
> )
> ```
>
> ### Fetch Midpoints
>
> Both `AsyncPublicClient` and `AsyncSecureClient` provide single and batch
> midpoint reads.
>
> ```python Before theme={null}
> from py_clob_client_v2 import BookParams
>
> midpoint = client.get_midpoint("TOKEN_ID")
> midpoints = client.get_midpoints(
>     [BookParams(token_id="TOKEN_ID_1"), BookParams(token_id="TOKEN_ID_2")]
> )
> ```
>
> ```python After theme={null}
> midpoint = await client.get_midpoint(asset_id="ASSET_ID")
> midpoints = await client.get_midpoints(asset_ids=["ASSET_ID_1", "ASSET_ID_2"])
> ```
>
> ### Fetch Spreads
>
> Both `AsyncPublicClient` and `AsyncSecureClient` provide single and batch spread
> reads.
>
> ```python Before theme={null}
> from py_clob_client_v2 import BookParams
>
> spread = client.get_spread("TOKEN_ID")
> spreads = client.get_spreads(
>     [BookParams(token_id="TOKEN_ID_1"), BookParams(token_id="TOKEN_ID_2")]
> )
> ```
>
> ```python After theme={null}
> spread = await client.get_spread(asset_id="ASSET_ID")
> spreads = await client.get_spreads(asset_ids=["ASSET_ID_1", "ASSET_ID_2"])
> ```
>
> ### Fetch Last Trade Prices
>
> Both `AsyncPublicClient` and `AsyncSecureClient` provide singular and batch
> methods for last-trade prices.
>
> ```python Before theme={null}
> from py_clob_client_v2 import BookParams
>
> last_trade = client.get_last_trade_price("TOKEN_ID")
> last_trades = client.get_last_trades_prices(
>     [BookParams(token_id="TOKEN_ID_1"), BookParams(token_id="TOKEN_ID_2")]
> )
> ```
>
> ```python After theme={null}
> last_trade = await client.get_last_trade_price(asset_id="ASSET_ID")
> last_trades = await client.get_last_trade_prices(
>     asset_ids=["ASSET_ID_1", "ASSET_ID_2"]
> )
> ```
>
> ### Fetch Price History
>
> Both `AsyncPublicClient` and `AsyncSecureClient` provide a price history
> paginator. Pass parameters as keyword arguments; each page contains typed points.
>
> ```python Before theme={null}
> from py_clob_client_v2 import PricesHistoryParams
>
> history = client.get_prices_history(
>     PricesHistoryParams(market="TOKEN_ID", interval="1d", fidelity=60)
> )
> ```
>
> ```python After theme={null}
> pages = client.list_price_history(
>     asset_id="ASSET_ID",
>     interval="1d",
>     bucket_seconds=3600,
> )
> page = await pages.first_page()
> history = page.items
> ```
>
> ### Estimate a Market Order Price
>
> Both `AsyncPublicClient` and `AsyncSecureClient` provide market-order price
> estimates. Buys specify collateral spent, while sells specify shares sold.
>
> ```python Before theme={null}
> from py_clob_client_v2 import OrderType, Side
>
> buy_price = client.calculate_market_price(
>     "TOKEN_ID", Side.BUY, 10, OrderType.FOK
> )
> sell_price = client.calculate_market_price(
>     "TOKEN_ID", Side.SELL, 5, OrderType.FOK
> )
> ```
>
> ```python After theme={null}
> buy_price = await client.estimate_market_price(
>     asset_id="ASSET_ID", side="BUY", amount=10, order_type="FOK"
> )
> sell_price = await client.estimate_market_price(
>     asset_id="ASSET_ID", side="SELL", shares=5, order_type="FOK"
> )
> ```
>
> ### List Recent Market Trades
>
> Both `AsyncPublicClient` and `AsyncSecureClient` provide the public trade
> paginator, which replaces the previous market-events response.
>
> ```python Before theme={null}
> trades = client.get_market_trades_events("CONDITION_ID")
> ```
>
> ```python After theme={null}
> pages = client.list_trades(condition_id=["CONDITION_ID"])
> page = await pages.first_page()
> trades = page.items
> ```
>
> ## Orders
>
> ### Place a Limit Order
>
> `AsyncSecureClient` resolves tick size, negative-risk status, fees, and signing
> details before submitting a limit order.
>
> ```python Before theme={null}
> from py_clob_client_v2 import OrderArgs, Side
>
> response = client.create_and_post_order(
>     OrderArgs(
>         token_id="TOKEN_ID",
>         price=0.52,
>         size=10,
>         side=Side.BUY,
>     )
> )
> ```
>
> ```python After theme={null}
> response = await client.place_limit_order(
>     asset_id="ASSET_ID",
>     price=0.52,
>     size=10,
>     side="BUY",
> )
> ```
>
> ### Place a Market Order
>
> `AsyncSecureClient` places market orders. Buys specify collateral to spend,
> while sells specify shares to sell.
>
> ```python Before theme={null}
> from py_clob_client_v2 import MarketOrderArgs, OrderType, Side
>
> response = client.create_and_post_market_order(
>     MarketOrderArgs(
>         token_id="TOKEN_ID",
>         amount=10,
>         user_usdc_balance=10,
>         side=Side.BUY,
>     ),
>     order_type=OrderType.FOK,
> )
> ```
>
> ```python After theme={null}
> response = await client.place_market_order(
>     asset_id="ASSET_ID",
>     side="BUY",
>     amount=10,
>     max_spend=10,
>     order_type="FOK",
> )
> ```
>
> `user_usdc_balance` becomes `max_spend`. The previous field supplied the
> account balance used to adjust the order for fees; the unified SDK instead
> accepts the maximum total USD to spend. Set `max_spend` equal to `amount` when
> the amount should include fees, or omit it to pay applicable fees on top.
>
> ### Sign Without Posting
>
> `AsyncSecureClient` provides order-type-specific creation methods when signing
> and submission need to happen separately.
>
> ```python Before theme={null}
> from py_clob_client_v2 import MarketOrderArgs, OrderArgs, Side
>
> limit_order = client.create_order(
>     OrderArgs(token_id="TOKEN_ID", price=0.52, size=10, side=Side.BUY)
> )
> market_order = client.create_market_order(
>     MarketOrderArgs(token_id="TOKEN_ID", amount=10, side=Side.BUY)
> )
> ```
>
> ```python After theme={null}
> limit_order = await client.create_limit_order(
>     asset_id="ASSET_ID",
>     price=0.52,
>     size=10,
>     side="BUY",
> )
> market_order = await client.create_market_order(
>     asset_id="ASSET_ID",
>     side="BUY",
>     amount=10,
> )
> ```
>
> ### Post Several Orders
>
> `AsyncSecureClient` provides `post_orders`. Order type and post-only behavior
> are part of each signed order, so the method accepts signed orders directly.
>
> ```python Before theme={null}
> from py_clob_client_v2 import OrderType, PostOrdersV2Args
>
> responses = client.post_orders(
>     [
>         PostOrdersV2Args(order=first_order, orderType=OrderType.GTC),
>         PostOrdersV2Args(order=second_order, orderType=OrderType.GTC),
>     ]
> )
> ```
>
> ```python After theme={null}
> responses = await client.post_orders([first_order, second_order])
> ```
>
> ### Attribute an Order to a Builder
>
> `AsyncSecureClient` attaches the builder code to each order.
>
> ```python Before theme={null}
> from py_clob_client_v2 import OrderArgs, Side
>
> response = client.create_and_post_order(
>     OrderArgs(
>         token_id="TOKEN_ID",
>         price=0.52,
>         size=10,
>         side=Side.BUY,
>         builder_code="BUILDER_CODE",
>     )
> )
> ```
>
> ```python After theme={null}
> response = await client.place_limit_order(
>     asset_id="ASSET_ID",
>     price=0.52,
>     size=10,
>     side="BUY",
>     builder_code="BUILDER_CODE",
> )
> ```
>
> ### Cancel Orders
>
> `AsyncSecureClient` provides explicit methods for cancelling one order,
> several orders, all orders, or orders for a market.
>
> ```python Before theme={null}
> from py_clob_client_v2 import OrderMarketCancelParams, OrderPayload
>
> client.cancel_order(OrderPayload(orderID="ORDER_ID"))
> client.cancel_orders(["ORDER_ID_1", "ORDER_ID_2"])
> client.cancel_market_orders(OrderMarketCancelParams(market="CONDITION_ID"))
> client.cancel_all()
> ```
>
> ```python After theme={null}
> await client.cancel_order(order_id="ORDER_ID")
> await client.cancel_orders(order_ids=["ORDER_ID_1", "ORDER_ID_2"])
> await client.cancel_market_orders(market="CONDITION_ID")
> await client.cancel_all()
> ```
>
> ### Fetch an Order
>
> `AsyncSecureClient` fetches an order by ID using a keyword argument.
>
> ```python Before theme={null}
> order = client.get_order("ORDER_ID")
> ```
>
> ```python After theme={null}
> order = await client.get_order(order_id="ORDER_ID")
> ```
>
> ### List Open Orders
>
> `AsyncSecureClient` provides `list_open_orders`, which returns an async
> paginator.
>
> ```python Before theme={null}
> from py_clob_client_v2 import OpenOrderParams
>
> orders = client.get_open_orders(
>     OpenOrderParams(market="CONDITION_ID", asset_id="TOKEN_ID")
> )
> ```
>
> ```python After theme={null}
> pages = client.list_open_orders(market="CONDITION_ID", asset_id="ASSET_ID")
> orders = [order async for order in pages.iter_items()]
> ```
>
> ### Check Order Scoring
>
> `AsyncSecureClient` provides `get_order_scoring` for one order and
> `get_orders_scoring` for several.
>
> ```python Before theme={null}
> from py_clob_client_v2 import OrderScoringParams, OrdersScoringParams
>
> scoring = client.is_order_scoring(OrderScoringParams(orderId="ORDER_ID"))
> batch = client.are_orders_scoring(
>     OrdersScoringParams(orderIds=["ORDER_ID_1", "ORDER_ID_2"])
> )
> ```
>
> ```python After theme={null}
> scoring = await client.get_order_scoring(order_id="ORDER_ID")
> batch = await client.get_orders_scoring(
>     order_ids=["ORDER_ID_1", "ORDER_ID_2"]
> )
> ```
>
> ## Account Activity and Balances
>
> ### List Account Trades
>
> `AsyncSecureClient` replaces both previous account trade-history methods with one
> async paginator.
>
> ```python Before theme={null}
> from py_clob_client_v2 import TradeParams
>
> trades = client.get_trades(TradeParams(market="CONDITION_ID"))
> page = client.get_trades_paginated(TradeParams(market="CONDITION_ID"))
> ```
>
> ```python After theme={null}
> pages = client.list_account_trades(market="CONDITION_ID")
> first_page = await pages.first_page()
>
> trades = [trade async for trade in pages.iter_items()]
> ```
>
> ### List Builder Trades
>
> Both `AsyncPublicClient` and `AsyncSecureClient` provide public builder trade
> history, filtered by builder code.
>
> ```python Before theme={null}
> from py_clob_client_v2 import BuilderTradeParams
>
> page = client.get_builder_trades(
>     BuilderTradeParams(builder_code="BUILDER_CODE")
> )
> trades = page["trades"]
> ```
>
> ```python After theme={null}
> pages = client.list_builder_trades(builder_code="BUILDER_CODE")
> page = await pages.first_page()
> trades = page.items
> ```
>
> ### Read and Drop Notifications
>
> `AsyncSecureClient` provides notification methods with keyword arguments and
> typed responses.
>
> ```python Before theme={null}
> from py_clob_client_v2 import DropNotificationParams
>
> notifications = client.get_notifications()
> client.drop_notifications(DropNotificationParams(ids=[1, 2]))
> ```
>
> ```python After theme={null}
> notifications = await client.get_notifications()
> await client.drop_notifications(ids=["1", "2"])
> ```
>
> ### Refresh Balances and Allowances
>
> `AsyncSecureClient` reads balances and manages missing allowances while placing
> orders. It completes the required approval, refreshes the allowance, and
> retries the order.
>
> ```python Before theme={null}
> from py_clob_client_v2 import AssetType, BalanceAllowanceParams
>
> params = BalanceAllowanceParams(asset_type=AssetType.COLLATERAL)
> client.update_balance_allowance(params)
> balance = client.get_balance_allowance(params)
> ```
>
> ```python After theme={null}
> balance = await client.get_balance_allowance(asset_type="COLLATERAL")
> response = await client.place_limit_order(
>     asset_id="ASSET_ID",
>     price=0.52,
>     size=10,
>     side="BUY",
> )
> ```
>
> ## Positions
>
> The unified methods build and submit wallet transactions. You no longer need to
> encode contract calls or pass transaction arrays to `execute`.
>
> ### Split a Position
>
> `AsyncSecureClient` splits collateral into a complete set of YES and NO outcome
> tokens.
>
> ```python Before theme={null}
> from py_builder_relayer_client.models import Transaction
>
> split_tx = Transaction(
>     to=CTF_COLLATERAL_ADAPTER_ADDRESS,
>     data=collateral_adapter.encode_abi(
>         "splitPosition",
>         args=[PUSD_ADDRESS, bytes(32), CONDITION_ID, [1, 2], 1_000_000],
>     ),
>     value="0",
> )
>
> split = relayer.execute([split_tx], "Split position")
> split.wait()
> ```
>
> ```python After theme={null}
> split = await client.split_position(
>     condition_id="CONDITION_ID",
>     amount=1_000_000,
> )
> await split.wait()
> ```
>
> ### Merge Positions
>
> `AsyncSecureClient` merges balanced YES and NO tokens back into collateral.
>
> ```python Before theme={null}
> from py_builder_relayer_client.models import Transaction
>
> merge_tx = Transaction(
>     to=CTF_COLLATERAL_ADAPTER_ADDRESS,
>     data=collateral_adapter.encode_abi(
>         "mergePositions",
>         args=[PUSD_ADDRESS, bytes(32), CONDITION_ID, [1, 2], 1_000_000],
>     ),
>     value="0",
> )
>
> merge = relayer.execute([merge_tx], "Merge positions")
> merge.wait()
> ```
>
> ```python After theme={null}
> merge = await client.merge_positions(
>     condition_id="CONDITION_ID",
>     amount="max",
> )
> await merge.wait()
> ```
>
> ### Redeem Resolved Positions
>
> `AsyncSecureClient` redeems winning outcome tokens for collateral after
> resolution.
>
> ```python Before theme={null}
> from py_builder_relayer_client.models import Transaction
>
> redeem_tx = Transaction(
>     to=CTF_COLLATERAL_ADAPTER_ADDRESS,
>     data=collateral_adapter.encode_abi(
>         "redeemPositions",
>         args=[PUSD_ADDRESS, bytes(32), CONDITION_ID, [1, 2]],
>     ),
>     value="0",
> )
>
> redeem = relayer.execute([redeem_tx], "Redeem positions")
> redeem.wait()
> ```
>
> ```python After theme={null}
> redeem = await client.redeem_positions(condition_id="CONDITION_ID")
> await redeem.wait()
> ```
>
> ## Service Status
>
> Neither `AsyncPublicClient` nor `AsyncSecureClient` requires these calls. The
> unified clients manage request timing internally.
>
> ```python Before theme={null}
> client.get_ok()
> timestamp = client.get_server_time()
> ```
>
> ```python After theme={null}
> # No client call is required for request timestamp synchronization.
> ```

> [tab] Rust
>
> A unified Rust SDK is in progress. Until it is available, use
> `polymarket_client_sdk_v2` `0.7.0`, the current Rust SDK.
>
> See the [GitHub repository](https://github.com/Polymarket/rs-clob-client-v2) and
> the [`polymarket_client_sdk_v2` package on crates.io](https://crates.io/crates/polymarket_client_sdk_v2)
> for the complete API and examples.
>
> ## Install the Rust SDK
>
> Enable the `clob` feature for authentication and trading:
>
> ```bash theme={null}
> cargo add polymarket_client_sdk_v2@0.7.0 --features clob
> ```
>
> ## Trade From a Deposit Wallet
>
> The Rust SDK supports the CLOB order path for an existing Deposit Wallet. It
> does not include a client for deploying Deposit Wallets or submitting wallet
> batches; use the Direct API workflows for those actions.
>
> Pass the deployed Deposit Wallet as the funder and use
> `SignatureType::Poly1271` when authenticating. This example refreshes the
> collateral allowance cache, then places a GTC limit buy:
>
> ```rust theme={null}
> use std::str::FromStr as _;
>
> use alloy::signers::Signer as _;
> use alloy::signers::local::LocalSigner;
> use polymarket_client_sdk_v2::clob::types::request::UpdateBalanceAllowanceRequest;
> use polymarket_client_sdk_v2::clob::types::{
>     AssetType, OrderType, Side, SignatureType,
> };
> use polymarket_client_sdk_v2::clob::{Client, Config};
> use polymarket_client_sdk_v2::types::{Address, Decimal, U256};
> use polymarket_client_sdk_v2::{POLYGON, PRIVATE_KEY_VAR};
>
> #[tokio::main]
> async fn main() -> anyhow::Result<()> {
>     let host = "https://clob-v2.polymarket.com";
>     let signer = LocalSigner::from_str(&std::env::var(PRIVATE_KEY_VAR)?)?
>         .with_chain_id(Some(POLYGON));
>     let deposit_wallet = Address::from_str(&std::env::var("DEPOSIT_WALLET")?)?;
>
>     let client = Client::new(host, Config::default())?
>         .authentication_builder(&signer)
>         .funder(deposit_wallet)
>         .signature_type(SignatureType::Poly1271)
>         .authenticate()
>         .await?;
>
>     client
>         .update_balance_allowance(
>             UpdateBalanceAllowanceRequest::builder()
>                 .asset_type(AssetType::Collateral)
>                 .build(),
>         )
>         .await?;
>
>     let response = client
>         .limit_order()
>         .token_id(U256::from_str(&std::env::var("TOKEN_ID")?)?)
>         .side(Side::Buy)
>         .price(Decimal::from_str("0.40")?)
>         .size(Decimal::from_str("100")?)
>         .order_type(OrderType::GTC)
>         .build_sign_and_post(&signer)
>         .await?;
>
>     println!("order_id={} status={}", response.order_id, response.status);
>     Ok(())
> }
> ```
>
> ## Handle Matching Engine Restarts
>
> Rebuild and re-sign an order before each retry because `SignedOrder` is
> consumed when it is submitted. Treat HTTP `425` as temporary and retry with
> exponential backoff:
>
> ```rust theme={null}
> use polymarket_client_sdk_v2::error::{Kind, StatusCode};
>
> let mut delay = std::time::Duration::from_secs(1);
>
> for _ in 0..10 {
>     let order = client.limit_order()
>         .token_id(token_id).price(price).size(size).side(side)
>         .build().await?;
>     let signed = client.sign(&signer, order).await?;
>
>     match client.post_order(signed).await {
>         Ok(response) => return Ok(response),
>         Err(err) if err.kind() == Kind::Status => {
>             if let Some(status) = err.downcast_ref::<polymarket_client_sdk_v2::error::Status>() {
>                 if status.status_code == StatusCode::from_u16(425).unwrap() {
>                     eprintln!("Engine restarting, retrying in {delay:?}...");
>                     tokio::time::sleep(delay).await;
>                     delay = (delay * 2).min(std::time::Duration::from_secs(30));
>                     continue;
>                 }
>             }
>             return Err(err);
>         }
>         Err(err) => return Err(err),
>     }
> }
> ```
>
> See [Matching Engine Restarts](https://docs.polymarket.com/trading/matching-engine.md) for the restart window,
> post-only period, and restricted-mode responses.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.