> ## 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. # Fund Your Account > Deposit and withdraw pUSD collateral for Perps trading Fund the Perps account with pUSD before placing orders. Deposits move pUSD from the user's Polymarket wallet into the Perps account. Withdrawals move available pUSD back to the authenticated wallet. ## Deposit Collateral Deposit pUSD when the account needs collateral for opening or maintaining Perps positions. Create a `SecureClient` for the wallet that will fund the Perps account. If you already have a Polymarket wallet, pass it as `wallet` and include a Relayer API key so the SDK can submit gasless transactions. If you are creating a wallet programmatically, use a Builder API key so the SDK can create the Deposit Wallet for that signer. ```ts Existing Account 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.PRIVATE_KEY!), apiKey: relayerApiKey({ key: process.env.RELAYER_API_KEY!, address: process.env.RELAYER_API_KEY_ADDRESS!, }), }); ``` ```ts New Programmatic Wallet 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.PRIVATE_KEY!), apiKey: builderApiKey({ key: process.env.BUILDER_API_KEY!, secret: process.env.BUILDER_SECRET!, passphrase: process.env.BUILDER_PASSPHRASE!, }), }); ``` Set up the approvals required for Perps collateral deposits. The SDK skips work that is already complete. ```ts theme={null} await client.setupTradingApprovals(); ``` Deposit pUSD from the user's Polymarket wallet into the Perps account. Make sure the wallet has pUSD before depositing. The minimum Perps deposit is 10 pUSD. Amounts use raw pUSD base units, so 10 pUSD is `10_000_000n`. ```ts theme={null} const deposit = await client.depositToPerps({ amount: 10_000_000n, }); const receipt = await deposit.wait(); // receipt.transactionHash: TxHash ``` `deposit.wait()` confirms that the chain transaction settled. Perps may take a moment to credit the account after that. Open a Perps session and read account state after the deposit settles. ```ts theme={null} const session = await client.openPerpsSession(); try { const portfolio = await session.fetchPortfolio(); const deposits = await session.listDeposits().firstPage(); } finally { await session.close(); } ``` Use `portfolio.withdrawable` to check available collateral and `deposits.items` to reconcile deposit history. Create an `AsyncSecureClient` for the wallet that will fund the Perps account. If you already have a Polymarket wallet, pass it as `wallet` and include a Relayer API key so the SDK can submit gasless transactions. If you are creating a wallet programmatically, use a Builder API key so the SDK can create the Deposit Wallet for that signer. ```python Existing Account theme={null} import os from polymarket import AsyncSecureClient, RelayerApiKey client = await AsyncSecureClient.create( private_key=os.environ["PRIVATE_KEY"], wallet=os.environ["POLYMARKET_WALLET_ADDRESS"], api_key=RelayerApiKey( key=os.environ["RELAYER_API_KEY"], address=os.environ["RELAYER_API_KEY_ADDRESS"], ), ) ``` ```python New Programmatic Wallet theme={null} import os from polymarket import AsyncSecureClient, BuilderApiKey client = await AsyncSecureClient.create( private_key=os.environ["PRIVATE_KEY"], api_key=BuilderApiKey( key=os.environ["BUILDER_API_KEY"], secret=os.environ["BUILDER_SECRET"], passphrase=os.environ["BUILDER_PASSPHRASE"], ), ) ``` Set up the approvals required for Perps collateral deposits. The SDK skips work that is already complete. ```python theme={null} await client.setup_trading_approvals() ``` Deposit pUSD from the user's Polymarket wallet into the Perps account. Make sure the wallet has pUSD before depositing. The minimum Perps deposit is 10 pUSD. Amounts use raw pUSD base units, so 10 pUSD is `10_000_000`. ```python theme={null} deposit = await client.deposit_to_perps(amount=10_000_000) receipt = await deposit.wait() # receipt.transaction_hash: TransactionHash ``` `deposit.wait()` confirms that the chain transaction settled. Perps may take a moment to credit the account after that. Open a Perps session and read account state after the deposit settles. ```python theme={null} session = await client.open_perps_session() try: portfolio = await session.fetch_portfolio() deposits = await session.list_deposits().first_page() finally: await session.close() ``` Use `portfolio.withdrawable` to check available collateral and `deposits.items` to reconcile deposit history. Before depositing, the Polymarket wallet must approve the Perps deposit contract to spend pUSD. If the approval is already in place, skip the approval call. ```solidity Approval Call theme={null} pUSD.approve(PerpsDepositContract, maxUint256) ``` Use these contract addresses when building the approval call. | Contract | Address | | ---------------------- | -------------------------------------------- | | pUSD collateral token | `0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB` | | Perps deposit contract | `0xDCa4af75705dbB50f62437045afF9921947917d2` | The following steps show the Deposit Wallet batch path. If you are trading with a Safe or Poly Proxy wallet, use an SDK that handles the wallet-specific transaction flow for you. Create the Perps deposit call. Deposit amounts use pUSD base units, so 10 pUSD is `10000000`. ```solidity theme={null} function deposit(address token, uint256 amount, address to); ``` Encode the deposit calldata with these arguments. | Argument | Value | | -------- | -------------------------------------------- | | `token` | `0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB` | | `amount` | `10000000` | | `to` | Signer address for the Polymarket account. | Build the final ordered call list. Include the approval call first only when approval is needed. ```json Without Approval theme={null} [ { "target": "0xDCa4af75705dbB50f62437045afF9921947917d2", "value": "0", "data": "" } ] ``` ```json With Approval theme={null} [ { "target": "0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB", "value": "0", "data": "" }, { "target": "0xDCa4af75705dbB50f62437045afF9921947917d2", "value": "0", "data": "" } ] ``` Fetch a fresh `WALLET` nonce before submitting the Deposit Wallet batch. ```bash theme={null} curl -G "https://relayer-v2.polymarket.com/v1/account/transactions/params" \ -H "RELAYER_API_KEY: $RELAYER_API_KEY" \ -H "RELAYER_API_KEY_ADDRESS: $RELAYER_API_KEY_ADDRESS" \ --data-urlencode "address=" \ --data-urlencode "type=WALLET" ``` The response includes the nonce to sign with the batch. ```json theme={null} { "address": "", "nonce": "" } ``` Build the EIP-712 `Batch` typed data for the Deposit Wallet. Use the final ordered call list from the previous step, and omit the approval call when allowance is already sufficient. Set `deadline` to a Unix timestamp in seconds after which the relayer should reject the batch. ```json theme={null} { "domain": { "name": "DepositWallet", "version": "1", "chainId": 137, "verifyingContract": "" }, "primaryType": "Batch", "types": { "Call": [ { "name": "target", "type": "address" }, { "name": "value", "type": "uint256" }, { "name": "data", "type": "bytes" } ], "Batch": [ { "name": "wallet", "type": "address" }, { "name": "nonce", "type": "uint256" }, { "name": "deadline", "type": "uint256" }, { "name": "calls", "type": "Call[]" } ] }, "message": { "wallet": "", "nonce": "", "deadline": "", "calls": [ { "target": "0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB", "value": "0", "data": "" }, { "target": "0xDCa4af75705dbB50f62437045afF9921947917d2", "value": "0", "data": "" } ] } } ``` Sign this typed data with the signer for the Polymarket account. Submit the signed batch to the Relayer API. Use the same ordered call list you signed in the previous step. ```bash theme={null} curl -X POST "https://relayer-v2.polymarket.com/submit" \ -H "Content-Type: application/json" \ -H "RELAYER_API_KEY: $RELAYER_API_KEY" \ -H "RELAYER_API_KEY_ADDRESS: $RELAYER_API_KEY_ADDRESS" \ -d '{ "type": "WALLET", "from": "", "to": "0x00000000000Fb5C9ADea0298D729A0CB3823Cc07", "nonce": "", "signature": "", "metadata": "Deposit pUSD to Perps", "depositWalletParams": { "depositWallet": "", "deadline": "", "calls": [ { "target": "0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB", "value": "0", "data": "" }, { "target": "0xDCa4af75705dbB50f62437045afF9921947917d2", "value": "0", "data": "" } ] } }' ``` The response includes the relayer transaction ID. ```json theme={null} { "transactionID": "", "state": "STATE_NEW" } ``` Poll the relayer transaction until it reaches `STATE_CONFIRMED` before relying on the deposited collateral. ```bash theme={null} curl "https://relayer-v2.polymarket.com/v1/account/transactions/" \ -H "RELAYER_API_KEY: $RELAYER_API_KEY" \ -H "RELAYER_API_KEY_ADDRESS: $RELAYER_API_KEY_ADDRESS" ``` ```json theme={null} { "transaction_id": "", "transaction_hash": "", "state": "STATE_CONFIRMED", "error_msg": null } ``` Perps may take a moment to credit the account after the onchain transaction settles. Treat `STATE_FAILED` and `STATE_INVALID` as terminal failures. ## Withdraw Collateral Withdraw pUSD when the account has available collateral that should return to the authenticated wallet. Request a withdrawal to the authenticated wallet. Amounts use raw pUSD base units, so 10 pUSD is `10_000_000n`. ```ts theme={null} const withdrawalId = await client.withdrawFromPerps({ amount: 10_000_000n, }); ``` The SDK signs the withdrawal request with the Polymarket account signer and returns the Perps withdrawal ID. To track the withdrawal, open a Perps session and list withdrawals. ```ts theme={null} const session = await client.openPerpsSession(); try { const withdrawals = await session.listWithdrawals().firstPage(); } finally { await session.close(); } ``` For more details on authenticated sessions, see [Authenticated Sessions](/perps/authenticated-sessions). Request a withdrawal to the authenticated wallet. Amounts use raw pUSD base units, so 10 pUSD is `10_000_000`. ```python theme={null} withdrawal_id = await client.withdraw_from_perps(amount=10_000_000) ``` The SDK signs the withdrawal request with the Polymarket account signer and returns the Perps withdrawal ID. To track the withdrawal, open a Perps session and list withdrawals. ```python theme={null} session = await client.open_perps_session() try: withdrawals = await session.list_withdrawals().first_page() finally: await session.close() ``` For more details on authenticated sessions, see [Authenticated Sessions](/perps/authenticated-sessions). Create a `withdraw` operation with the account signer, pUSD token, raw token amount, and destination wallet. For withdrawals, `amount` is the raw pUSD token amount, so 10 pUSD is `10000000`. ```json theme={null} { "type": "withdraw", "args": { "account": "", "token": "0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB", "amount": "10000000", "to": "" } } ``` | Field | Value | | --------- | ------------------------------------------ | | `account` | Signer address for the Polymarket account. | | `token` | pUSD collateral token address. | | `amount` | Raw pUSD token amount. | | `to` | Wallet that receives the withdrawal. | The withdrawal signature uses EIP-712 typed data with `Withdraw` as the primary type. Use the same `account`, `token`, `amount`, and `to` values from the withdrawal operation. For withdrawals, `ts` is a Unix timestamp in seconds because the onchain contract validates it against `block.timestamp`. It must match the `ts` value in the request body. ```json theme={null} { "domain": { "name": "Polymarket", "version": "1", "chainId": 137, "verifyingContract": "0xDCa4af75705dbB50f62437045afF9921947917d2" }, "primaryType": "Withdraw", "types": { "Withdraw": [ { "name": "account", "type": "address" }, { "name": "token", "type": "address" }, { "name": "amount", "type": "uint256" }, { "name": "fee", "type": "uint256" }, { "name": "to", "type": "address" }, { "name": "salt", "type": "uint64" }, { "name": "ts", "type": "uint64" } ] }, "message": { "account": "", "token": "0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB", "amount": "10000000", "fee": "0", "to": "", "salt": 555555555, "ts": 1767000014 } } ``` | Field | Value | | ------ | ---------------------------------------------------- | | `salt` | Random integer generated for this signed request. | | `ts` | Current Unix timestamp in seconds, not milliseconds. | Sign the typed data with the Polymarket account signer. The example below uses Viem. ```ts Viem theme={null} import { privateKeyToAccount } from "viem/accounts"; const account = privateKeyToAccount(""); const signature = await account.signTypedData({ domain: { name: "Polymarket", version: "1", chainId: 137, verifyingContract: "0xDCa4af75705dbB50f62437045afF9921947917d2", }, primaryType: "Withdraw", types: { Withdraw: [ { name: "account", type: "address" }, { name: "token", type: "address" }, { name: "amount", type: "uint256" }, { name: "fee", type: "uint256" }, { name: "to", type: "address" }, { name: "salt", type: "uint64" }, { name: "ts", type: "uint64" }, ], }, message: { account: "", token: "0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB", amount: 10000000n, fee: 0n, to: "", salt: 555555555n, ts: 1767000014n, }, }); ``` Submit the signed withdrawal request to `POST /v1/account/withdraw`. Use the same operation values, `salt`, and `ts` from the typed data. ```bash theme={null} curl -X POST "https://api.perpetuals.polymarket.com/v1/account/withdraw" \ -H "content-type: application/json" \ -d '{ "op": { "type": "withdraw", "args": { "account": "", "token": "0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB", "amount": "10000000", "to": "" } }, "sig": "", "salt": 555555555, "ts": 1767000014 }' ``` The response indicates whether the withdrawal was accepted. ```json Success theme={null} { "status": "ok", "withdraw_id": 1234567890 } ``` ```json Failure theme={null} { "status": "err", "withdraw_id": 1234567890, "error": "insufficient_balance" } ``` Use the returned `withdraw_id` to match the withdrawal against history results. ```bash theme={null} curl -G "https://api.perpetuals.polymarket.com/v1/account/withdrawals" \ -H "polymarket-proxy: " \ -H "polymarket-secret: " \ --data-urlencode "withdrawal_status=pending" ``` For more details on proxy credentials and private account-read headers, see [Authenticated Sessions](/perps/authenticated-sessions). ## Review Funding History Use deposit and withdrawal history to reconcile collateral movements after your integration submits funding requests. See [Authenticated Sessions](/perps/authenticated-sessions) for how to create an authenticated session for private account history reads. List deposit or withdrawal history from an authenticated Perps session. ```ts Deposits theme={null} import type { PerpsDeposit } from "@polymarket/client"; const session = await client.openPerpsSession(); try { const deposits: PerpsDeposit[] = []; for await (const page of session.listDeposits()) { deposits.push(...page.items); } } finally { await session.close(); } ``` ```ts Withdrawals theme={null} import type { PerpsWithdrawal } from "@polymarket/client"; const session = await client.openPerpsSession(); try { const withdrawals: PerpsWithdrawal[] = []; for await (const page of session.listWithdrawals()) { withdrawals.push(...page.items); } } finally { await session.close(); } ``` List deposit or withdrawal history from an authenticated Perps session. ```python Deposits theme={null} session = await client.open_perps_session() try: deposits = [] async for page in session.list_deposits(): deposits.extend(page.items) finally: await session.close() ``` ```python Withdrawals theme={null} session = await client.open_perps_session() try: withdrawals = [] async for page in session.list_withdrawals(): withdrawals.extend(page.items) finally: await session.close() ``` List deposit history. ```bash theme={null} curl -G "https://api.perpetuals.polymarket.com/v1/account/deposits" \ -H "polymarket-proxy: " \ -H "polymarket-secret: " ``` List withdrawal history. ```bash theme={null} curl -G "https://api.perpetuals.polymarket.com/v1/account/withdrawals" \ -H "polymarket-proxy: " \ -H "polymarket-secret: " ``` Use the optional `deposit_status`, `withdrawal_status`, `start_timestamp`, and `end_timestamp` query parameters when reconciling a specific window.