A secure NestJS-based proxy API for Polymarket's Gamma (public) and CLOB (private) APIs with built-in credential management and authentication.
- Install dependencies:
npm install- Configure environment variables:
cp conf/env.example conf/.env
# Edit conf/.env with your actual configuration values- Required environment variables:
POLYMARKET_API_STAGE- Application stage (dev, staging, prod)JWT_SECRET- Secret key for JWT token signingMONGO_URI- MongoDB connection stringREDIS_URL- Redis connection URLREDIS_HOST- Redis hostREDIS_PORT- Redis portREDIS_PASSWORD- Redis password (if required)LOG_LEVEL- Logging level (info, debug, error, etc.)DISABLE_SWAGGER- Set to 'true' to disable Swagger UIINSTRUMENT- Enable instrumentationPORT- Server port (default: 3000)VERBOSE_ERRORS- Enable verbose error messagesAWS_SECRET_NAME- AWS Secrets Manager secret nameERROR_EMAILS- Comma-separated list of error notification emails
- Build the application:
npm run build- Start the application:
npm startThis is a monorepo built with NX workspace.
Main Application (apps/polymarkets-api/)
- Entry point with Swagger UI setup
- Global exception filters
- Environment validation
Polymarket Module (libs/main/src/polymarket/)
- Public endpoints (markets, events, search, sports)
- Private endpoints (orders, trades, balances)
- Order placement (limit & market orders)
- Batch order support
Polymarket Auth Module (libs/main/src/polymarket-auth/)
- CLOB client management
- Private key derivation
- API credential handling
User Polymarket Credentials Module (libs/main/src/user-polymarket-credentials/)
- Connect/disconnect endpoints
- Encrypted credential storage (MongoDB)
- Supports two authentication flows:
- Private key flow (derives API credentials)
- Direct API credentials flow
Shared Module (libs/main/src/shared/)
- Crypto service (AES-256 encryption)
- Logger service with configurable levels
- JWT guards and decorators
- Token expiry middleware
- Get JWT Token - Authenticate with your application to get a JWT token
- Connect to Polymarket -
POST /v1/user-polymarket-credentials/connectwith your private key - Use Authenticated Endpoints - All private endpoints are now available with your JWT token
- Disconnect (Optional) -
POST /v1/user-polymarket-credentials/disconnectto remove credentials
The API is organized into two main categories:
Public endpoints use Polymarket's Gamma API and don't require authentication or stored credentials.
Markets
GET /v1/polymarket/markets- List markets with filtering- Query:
limit,offset,active,closed
- Query:
GET /v1/polymarket/markets/:slug- Get market details by slug
Events
GET /v1/polymarket/events- List events with filtering- Query:
limit,offset,active,closed,featured
- Query:
GET /v1/polymarket/events/:slug- Get event details by slug
Discovery
GET /v1/polymarket/tags- Get available tags/categoriesGET /v1/polymarket/sports- Get sports teams- Query:
limit,offset,order,ascending,league,name,abbreviation
- Query:
GET /v1/polymarket/search- Search across markets, events, tags, profiles- Query:
q(required),limit,page
- Query:
GET /v1/polymarket/positions- Get positions for a wallet address- Query:
user(required),market,eventId,sizeThreshold,redeemable,mergeable,limit,offset,sortBy,sortDirection
- Query:
Private endpoints require JWT authentication and use Polymarket's CLOB API.
Header required for all private endpoints:
Authorization: Bearer <your-jwt-token>
Connection Management
POST /v1/user-polymarket-credentials/connect- Connect wallet to Polymarket- Body:
private_keyOR (api_key,api_secret,api_passphrase,wallet_address) - Optional:
funder_address,wallet_type - Supports two flows:
- Private key flow: Derives API credentials automatically
- Direct credentials flow: Use existing API credentials
- Body:
POST /v1/user-polymarket-credentials/disconnect- Disconnect and remove credentials
Orders
POST /v1/polymarket/orders- Place an order- Limit orders (GTC/GTD):
tokenID,side,price,size,orderType,expiration(if GTD) - Market orders (FOK/FAK):
tokenID,side,amount,orderType, optionalpricefor slippage protection
- Limit orders (GTC/GTD):
POST /v1/polymarket/orders/batch- Place up to 15 orders at once- Body:
ordersarray
- Body:
GET /v1/polymarket/orders- Get open orders- Query:
id,market,asset_id,only_first_page,next_cursor
- Query:
GET /v1/polymarket/orders/:id- Get specific order detailsDELETE /v1/polymarket/orders/:id- Cancel a specific orderDELETE /v1/polymarket/orders- Cancel multiple orders- Body:
order_idsarray
- Body:
DELETE /v1/polymarket/orders/market/:marketId- Cancel all orders for a market
Trades
GET /v1/polymarket/trades- Get trade history- Query:
id,taker_address,maker_address,market,asset_id,before,after,only_first_page,next_cursor
- Query:
GET /v1/polymarket/trades/:id- Get specific trade details
Balances
GET /v1/polymarket/balances- Get USDC balances- Returns:
balance,signerBalance,signerAddress, optionallyfunderBalance,funderAddress
- Returns:
Prices
GET /v1/polymarket/markets/:tokenId/last-trade-price- Get last trade price for a token
Run the application in development mode:
npm run build
npm startThe API will be available at http://localhost:3000/v1 and Swagger documentation at http://localhost:3000/api
- All private keys and API credentials are encrypted using AES-256 before storage
- Credentials are stored per user (linked to JWT user_id)
- Private keys are never returned in API responses
- Wallet addresses are stored unencrypted for reference only