Skip to main content
Polymarket’s Builder program enables apps to earn fees on trades they route through the platform. This guide demonstrates how to integrate Polymarket trading using Privy for authentication and embedded wallet provisioning—giving your users a seamless, gasless trading experience with web2-style onboarding.

Polymarket builder code example repo

Official Next.js example with Privy authentication and Polymarket trading.

Getting started

1

Create a Privy app

Sign up at dashboard.privy.io and create an app.
2

Get builder credentials

Obtain your builder API key, secret, and passphrase from Polymarket.
3

Get a Polygon RPC URL

Use any Polygon mainnet RPC provider (Alchemy, Infura, or a public RPC).

Setup

To get started, you’ll need to set up:
  • Privy authentication — Handles login and provisions embedded wallets
  • Builder signing endpoint — Keeps your builder credentials secure server-side
  • Polymarket clients — RelayClient for Safe operations, ClobClient for trading
Clone the example:
git clone https://github.com/Polymarket/privy-safe-builder-example.git
cd privy-safe-builder-example
npm install
Add your credentials to .env.local:
NEXT_PUBLIC_POLYGON_RPC_URL=your_rpc_url
NEXT_PUBLIC_PRIVY_APP_ID=your_privy_app_id
POLYMARKET_BUILDER_API_KEY=your_builder_api_key
POLYMARKET_BUILDER_SECRET=your_builder_secret
POLYMARKET_BUILDER_PASSPHRASE=your_builder_passphrase
Run npm run dev and open localhost:3000.

Integration steps

Step 1: Set up authentication

First, wrap your app with PrivyProvider and use Privy’s hooks to handle login. When users authenticate, Privy automatically provisions an embedded wallet:
import {PrivyProvider, usePrivy, useWallets} from '@privy-io/react-auth';

function App() {
  const {login, authenticated} = usePrivy();
  const {wallets} = useWallets();

  const embeddedWallet = wallets.find((w) => w.walletClientType === 'privy');

  return (
    <button onClick={login}>
      {authenticated ? `Connected: ${embeddedWallet?.address}` : 'Login'}
    </button>
  );
}

Step 2: Configure the builder signing endpoint

Next, set up a server-side API route to keep your builder credentials secure. The example includes this at app/api/polymarket/sign/route.ts. This endpoint generates HMAC signatures for the RelayClient and ClobClient:
const signature = buildHmacSignature(
  BUILDER_CREDENTIALS.secret,
  parseInt(sigTimestamp),
  method,
  path,
  requestBody
);

return NextResponse.json({
  POLY_BUILDER_SIGNATURE: signature,
  POLY_BUILDER_TIMESTAMP: sigTimestamp,
  POLY_BUILDER_API_KEY: BUILDER_CREDENTIALS.key,
  POLY_BUILDER_PASSPHRASE: BUILDER_CREDENTIALS.passphrase
});
This reference implementation exposes builder credentials to the client. For production, implement a proxy pattern where the server makes all CLOB/Relay requests, or add auth token validation before returning credentials.

Step 3: Deploy a Safe wallet

Polymarket uses Gnosis Safe wallets for trading. The hooks/useSafeDeployment.ts hook handles this. First, derive the Safe address from the user’s EOA (this is deterministic—the same EOA always gets the same Safe):
const config = getContractConfig(POLYGON_CHAIN_ID);
const safeAddress = deriveSafe(eoaAddress, config.SafeContracts.SafeFactory);
Then check if the Safe exists and deploy it if needed:
const deployed = await relayClient.getDeployed(safeAddress);

if (!deployed) {
  const response = await relayClient.deploy();
  const result = await relayClient.pollUntilState(response.transactionID, [...]);
  return result.proxyAddress;
}
The Safe holds the user’s USDC.e and outcome tokens. Deployment is gasless—Polymarket’s relayer covers the cost.

Step 4: Get user API credentials

User API Credentials authenticate requests to the CLOB. The hooks/useUserApiCredentials.ts hook handles this. For new users, create credentials:
const tempClient = new ClobClient('https://clob.polymarket.com', 137, ethersSigner);
const creds = await tempClient.createApiKey(); // Prompts for signature
For returning users, derive existing credentials:
const creds = await tempClient.deriveApiKey(); // Prompts for signature
Both methods require the user to sign an EIP-712 message. The example stores credentials in localStorage for convenience, but production apps should use secure httpOnly cookies or server-side session management.

Step 5: Set token approvals

Before trading, the Safe must approve Polymarket’s contracts. The hooks/useTokenApprovals.ts hook batches all approvals into a single transaction. USDC.e (ERC-20) approvals for:
  • CTF Contract: 0x4d97dcd97ec945f40cf65f87097ace5ea0476045
  • CTF Exchange: 0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E
  • Neg Risk Exchange: 0xC5d563A36AE78145C45a50134d48A1215220f80a
  • Neg Risk Adapter: 0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296
Outcome token (ERC-1155) approvals for:
  • CTF Exchange: 0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E
  • Neg Risk Exchange: 0xC5d563A36AE78145C45a50134d48A1215220f80a
  • Neg Risk Adapter: 0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296
const approvalStatus = await checkAllApprovals(safeAddress);

if (!approvalStatus.allApproved) {
  const approvalTxs = createAllApprovalTxs();
  const response = await relayClient.execute(approvalTxs, 'Set token approvals');
  await response.wait();
}
Approvals persist across sessions—users only sign once. All approval transactions are gasless via the relayer.

Step 6: Place an order

With the session initialized, place orders through the CLOB client:
const order = {
  tokenID: '0x...', // Outcome token from market
  price: 0.65, // 65 cents
  size: 10, // 10 shares
  side: 'BUY',
  feeRateBps: 0,
  expiration: 0, // Good-til-cancel
  taker: '0x0000000000000000000000000000000000000000'
};

const response = await clobClient.createAndPostOrder(order, {negRisk: false}, OrderType.GTC);
console.log('Order ID:', response.orderID);
Orders are signed by the user’s Privy EOA and executed from their Safe address. Builder attribution is automatic via the builder config.

Troubleshooting

Verify NEXT_PUBLIC_PRIVY_APP_ID is set correctly. Check that your domain is allowed in the Privy dashboard.
Check builder credentials in .env.local. Verify the /api/polymarket/sign endpoint is accessible.
Ensure the Polygon RPC URL is valid. The user must approve the signature via Privy.
The Safe must be deployed first. Verify the builder relay service is operational.
Verify the trading session is complete and the Safe has a USDC.e balance. Wait 2-3 seconds for CLOB sync.

Resources