Skip to main content
Every Polymarket trading endpoint requires a signatureByEvmEoa field — an EIP-712 signature produced by the user’s home EOA that authorizes the request. This page describes the typed-data schemas, the signing flow, and a working viem example.

Signature requirements

signatureByEvmEoa + expiration are required on every request to:

Expiration window

expiration is a Unix timestamp in seconds. The backend rejects:
  • expirations in the past,
  • expirations more than 300 seconds (5 minutes) in the future,
  • non-integer or non-finite values.
Compute it close to send time, e.g. Math.floor(Date.now() / 1000) + 60.

Typed-data schemas

All three schemas use the same EIP-712 domain shape — version: '1', chainId: 137 (Polygon). Only the domain name and the primaryType change. Address- and chainId-shaped fields are signed as string so absent optionals can be represented as the empty string "". When an optional is omitted from the request body, sign it as "" (not "0x0000..." or "0").

PlaceOrder — used by placeOrder

RedeemPosition — used by redeemPosition

SellPosition — used by sellPosition

Withdraw — used by withdraw

srcTokenAddress selects which token to withdraw from the proxy wallet (defaults to pUSD collateral when omitted). It is always on Polygon, so only the address is signed — there is no srcTokenChainId. dstToken selects the token delivered to dstWalletAddress.

Building the message

A few field-specific rules apply when assembling the message object:
  • Amount scaling. For PlaceOrder and SellPosition, amount is the USD amount scaled to 6 decimals: BigInt(Math.floor(amount * 1_000_000)). The request body still carries the un-scaled number (e.g. 2.5); the scaling applies only to the signed value.
  • uint256 fields. slippage and expiration must be bigint when signing (BigInt(slippage), BigInt(expiration)).
  • Empty-string optionals. Map omitted optionals to "":
    • srcTokenAddress absent (withdraw) → srcTokenAddress: "".
    • dstToken absent → dstTokenAddress: "", dstTokenChainId: "".
    • proxyWallet absent (sell) → proxyWallet: "".
  • Chain ID as string. When dstToken is present, sign dstTokenChainId: String(dstToken.chainId).

Example — sign and submit a placeOrder

The same pattern applies to redeemPosition and sellPosition — swap the domain name, primaryType, and types for the matching schema and include the additional dstTokenAddress, dstTokenChainId, and dstWalletAddress fields (using "" when their request-body counterpart is omitted).