Polymarket Bot Tutorial · Chapter 6 of 32
Polymarket bot authentication and wallet setup: proxy wallets vs EOA, API key generation via SDK, sigType 2 for Gnosis Safe, key storage best practices, and the Magic-to-Privy migration.
What this chapter covers
Polymarket's wallet model has three moving parts: an externally owned account (EOA) that signs orders, a smart-contract proxy that holds funds, and the Polymarket CLOB API key that authenticates HTTP requests. Getting all three wired correctly is the single most common Day 1 failure for new builders, and it became more confusing after the August 2025 Magic Labs to Privy migration. This chapter walks each piece in setup order, with the specific environment variables and signature-type flag that production code needs.
- Proxy wallet vs EOA: which to bot with
- Generating an API key (SDK steps)
- sigType 2 and POLY_FUNDER_ADDRESS (Gnosis Safe)
- Key storage: .env, vault, KMS
- The Magic Labs to Privy migration
- Approving USDC/pUSD spending
- Wallet recovery and backup
Proxy wallet vs EOA: which to bot with
Polymarket uses a smart-contract proxy wallet pattern. Your EOA - the address tied to your private key - signs transactions and orders. A Gnosis Safe deployed at a deterministic address holds the actual pUSD and outcome shares. The proxy address is what shows in the Polymarket UI's "wallet" panel; the EOA is what signs.
For bots, you always sign with the EOA (PRIVATE_KEY in env) and reference the proxy address as POLY_FUNDER_ADDRESS in the CLOB client config. Sending orders with the EOA as funder produces "insufficient balance" errors even when the proxy is funded.
You cannot bot with the EOA alone - Polymarket's web flow always creates a proxy on signup. Confirm both addresses with polymarket wallet show from the CLI, or read the proxy address from the Polymarket UI's settings.
Generating an API key (SDK steps)
The CLOB API requires three credentials: key, secret, passphrase. These are not your wallet private key - they are an HMAC-style credential set bound to your wallet, used for HTTP request authentication only.
Generate them once with the SDK:
# Python
from py_clob_client_v2 import ClobClient
c = ClobClient(host="https://clob.polymarket.com", chain_id=137,
key="<PRIVATE_KEY>", signature_type=2,
funder="<PROXY_ADDRESS>")
creds = c.create_or_derive_api_key() # V2 method (was create_or_derive_api_creds in V1)
print(creds.key, creds.secret, creds.passphrase) # V2 returns key / secret / passphrase
Store the output in a JSON file and load it on every bot start; do not regenerate per session - the API server caches the credential set, and rotating frequently can trip rate-limit logic. The credentials never expire automatically. Rotate them only if you suspect a leak.
sigType 2 and POLY_FUNDER_ADDRESS (Gnosis Safe)
The signature_type argument controls how the CLOB validates your order signatures. There are four:
- 0 / EOA: the EOA is both signer and funder. Used when a private key was imported directly.
- 1 / POLY_PROXY: Magic/email proxy contract. Many pre-2025 accounts.
- 2 / POLY_GNOSIS_SAFE: a Gnosis Safe holds funds, the EOA signs. Common current standard.
- 3 / POLY_1271: deposit wallets (EIP-1271 smart-contract signatures) - the type Polymarket recommends for new accounts. Today the Python/TS V2 clients have an open deposit-wallet signing bug, so use the Rust client for type 3 - see Authentication.
Use signature_type=2 for any account created after August 2025 (the Privy migration) or any account where you can see a Gnosis Safe address in the Polymarket UI. The POLY_FUNDER_ADDRESS env var must be the Safe address, not the EOA. Mismatched signature_type against the funder type silently produces order rejections that look like "insufficient allowance" or "balance: 0" - the error message is misleading.
Key storage: .env, vault, KMS
Three reasonable storage tiers for the EOA private key.
- .env file (single-machine development). The file lives on the VPS, the bot reads it on start, the key never leaves the host. Adequate for <$1k wallets.
chmod 600 .envand make sure your repo's .gitignore excludes it. - Self-hosted vault (HashiCorp Vault, age-encrypted file, or systemd-creds). Adds an unlock step on bot start. Worth it for wallets in the $1k-$10k range.
- Cloud KMS (AWS KMS, GCP KMS). The bot calls KMS to decrypt the key in memory; the key never touches disk. Worth the operational complexity only above $10k or for multi-bot fleets.
What to never do: commit a private key to git, paste it into a chat, store it in a password manager that syncs to cloud services without local-only mode. The on-chain blast radius of a Polymarket EOA leak is your entire pUSD balance and outcome share inventory.
The Magic Labs to Privy migration
In August 2025 Polymarket migrated their primary embedded-wallet provider from Magic Labs to Privy. The bot-facing effect is small but specific.
Pre-migration accounts (created via Magic) typically use signature_type=1 (POLY_PROXY). Post-migration accounts use signature_type=2 (POLY_GNOSIS_SAFE). Some users migrated their old account; some kept the original. There is no way to tell from the public API which type your account uses - you check by trying to sign an order and observing the rejection.
The migration also changed how the UI exposes the funder address. Older Polymarket UI flows showed the proxy address in the dashboard; the current flow buries it in account settings. The CLI command polymarket wallet show is the cleanest way to confirm both values, regardless of when the account was created.
Approving USDC/pUSD spending
For the CLOB to move your pUSD on order match, the proxy must have approved the Polymarket exchange contracts as spenders. The Polymarket UI sets these approvals during the first deposit. For bots that fund the proxy directly, you must set them manually.
Three approvals to set, once per wallet:
- pUSD (ERC-20) → exchange contract
- Conditional Tokens (ERC-1155) → exchange contract (for selling shares)
- Conditional Tokens (ERC-1155) → NegRisk exchange contract (for selling NegRisk shares)
Run polymarket approve from the CLI on first setup. The transaction costs a few cents in MATIC gas. Verify with polymarket approve check - all three should return "approved." The most common silent bug for new builders is missing the NegRisk approval, which fails only when selling shares from multi-outcome markets and looks like a balance error.
Wallet recovery and backup
The bot's wallet has two recoverable elements: the EOA private key, and the Polymarket account password (which gates access through the web UI but not through the SDK).
The EOA private key is the only thing that matters for the bot. Loss = loss of everything in the proxy. Cold backup: write it on paper, seal in an envelope, store offsite. Hot backup: encrypted USB stick. Never email it to yourself; never store unencrypted in cloud storage.
The Polymarket account password is recoverable via Magic Labs / Privy email recovery as long as you still control the original signup email. It does not gate bot access - the bot uses the EOA private key directly.
If you suspect a key leak: immediately withdraw pUSD and outcome tokens to a new wallet, generate a new EOA, redeploy the bot with the new key. The leaked key cannot be revoked; it can only be drained.










