LuckyLobster - Polymarket Trading API
Trade prediction markets on Polymarket through a secure API designed for AI agents.
How Polymarket Works
Polymarket is a prediction market where you trade on the outcomes of real-world events.
Buying Contracts:
- In active markets, you can buy outcome contracts priced from $0.01 to $0.99
- Each contract entitles you to 1 share at your purchase price
- Lower prices = higher potential return, but less likely outcome (market's view)
Selling Contracts:
- You can sell your shares at any time before the market closes
- Sell price depends on current market conditions
Market Resolution:
- When a market resolves, the winning outcome pays $1.00 USDC per share
- Losing outcomes pay $0 (or a negligible amount in rare cases)
Example: You buy 100 "Yes" shares at $0.35 each (cost: $35). If "Yes" wins, you receive $100 (profit: $65). If "No" wins, you lose your $35.
Setup
If you don't have an API key configured, use the device authorization flow to link your account.
Device Authorization Flow
Step 1: Request a Device Code
POST https://luckylobster.io/api/auth/device
Content-Type: application/json
{
"agent_name": "OpenClaw Agent"
}
Response:
{
"device_code": "abc123...",
"user_code": "ABCD-1234",
"verification_uri": "https://luckylobster.io/link",
"verification_uri_complete": "https://luckylobster.io/link?code=ABCD-1234",
"expires_in": 900,
"interval": 5
}
Step 2: Direct the User
Parse the JSON response and extract the verification_uri_complete field. Display it to the user as a clickable link:
🦞 To connect LuckyLobster, click: {verification_uri_complete}
Important: Use the verification_uri_complete value exactly as returned — do NOT concatenate fields or build the URL yourself. The value is a complete, ready-to-use URL.
Step 3: Poll for Authorization
Poll every 5 seconds until authorized:
GET https://luckylobster.io/api/auth/device/token?device_code=abc123...
Pending response:
{ "error": "authorization_pending" }
Success response:
{
"api_key": "ll_abc123...",
"user_email": "user@example.com",
"permissions": ["read", "trade", "cancel", "redeem"]
}
All linked agents receive standard permissions: read (view markets/orders/positions), trade (buy/sell), cancel (cancel orders), and redeem (settle positions).
Step 4: Store the API Key
Save the API key persistently so it survives restarts. It is only returned once.
Use the gateway tool with config.patch to save it in the skill config:
gateway.config.patch({
patch: {
skills: {
entries: {
luckylobster: {
env: {
LUCKYLOBSTER_API_KEY: "ll_abc123..."
}
}
}
}
}
})
Authentication
All API requests require an API key in the Authorization header:
Authorization: Bearer YOUR_API_KEY
Base URL
https://luckylobster.io/api/agent/v1
Rate Limits
- Default: 100 requests per minute
- Rate limit headers included in responses:
X-RateLimit-Limit: Max requests allowedX-RateLimit-Remaining: Requests remainingX-RateLimit-Reset: Reset time (ISO 8601)
Endpoints
Search Markets
Find prediction markets on Polymarket. The search uses smart relevance scoring to return the best matches first.
GET /markets/search?q={query}
Parameters:
q(required for search): Natural language query - "bitcoin 15m", "trump election", "superbowl winner"limit(optional): Max results (default: 10, max: 100)offset(optional): Pagination offsetsort(optional): "relevance" (default), "volume", "liquidity", "end_date", "recent"ending_soon(optional): Prioritize markets ending within 24h (default: false)min_volume(optional): Minimum volume in USD (default: 100)min_liquidity(optional): Minimum liquidity in USDtag(optional): Filter by category: "crypto", "politics", "sports", "entertainment"accepting_orders(optional): Only tradeable markets (default: true)
Search Tips:
- Shorthand supported: "btc 15m" → "Bitcoin Up or Down", "eth daily" → "Ethereum Up or Down on"
- The search auto-expands: btc→Bitcoin, eth→Ethereum, sol→Solana, etc.
- Time keywords (15m, hourly, daily) auto-expand to "Up or Down" queries
- Results are ranked by relevance: query match + liquidity + volume + accepting orders
- For time-sensitive markets, add
ending_soon=trueto prioritize markets expiring within 24h - First result is usually the best match - check
context.topMatch
Example - Find Current BTC Market:
curl -H "Authorization: Bearer $LUCKYLOBSTER_API_KEY" \
"https://luckylobster.io/api/agent/v1/markets/search?q=bitcoin%20up%20down&ending_soon=true&limit=5"
Example - High-Volume Politics Markets:
curl -H "Authorization: Bearer $LUCKYLOBSTER_API_KEY" \
"https://luckylobster.io/api/agent/v1/markets/search?q=election&tag=politics&sort=volume"
Response:
{
"success": true,
"data": [
{
"id": "1314069",
"slug": "bitcoin-up-or-down-on-february-3",
"question": "Bitcoin Up or Down on February 3?",
"outcomes": ["Up", "Down"],
"outcomePrices": ["0.65", "0.35"],
"volume": "409100.65",
"liquidity": "39255.13",
"endDate": "2026-02-03T17:00:00Z",
"active": true,
"acceptingOrders": true
}
],
"pagination": { "limit": 5, "offset": 0, "count": 1, "hasMore": false },
"context": {
"hasResults": true,
"topMatch": { "id": "1314069", "question": "Bitcoin Up or Down on February 3?", "acceptingOrders": true },
"endingSoonCount": 1
},
"options": {
"sortBy": ["relevance", "volume", "liquidity", "end_date", "recent"],
"tags": ["crypto", "politics", "sports", "entertainment"]
}
}
Workflow for Trading:
- Search:
GET /markets/search?q=bitcoin up down - Use the
idfrom the top result to get full details:GET /markets/{id} - Response includes
clobTokenIds- use these with trading endpoints
Quick Crypto Market Lookup
For crypto up/down markets, use this dedicated endpoint. It uses deterministic slug-based lookups (not text search) and is the most reliable way to find crypto markets:
GET /markets/crypto?asset={btc|eth|sol|xrp|doge|matic}&timeframe={daily|hourly|15m}
Examples:
/markets/crypto?asset=btc- Today's Bitcoin daily market/markets/crypto?asset=btc&timeframe=15m- Current Bitcoin 15-minute market/markets/crypto?asset=eth&timeframe=hourly- Current Ethereum hourly market/markets/crypto?asset=xrp&timeframe=15m- Current XRP 15-minute market
Response includes tokens array with tokenId, negRisk, and live spread data ready for trading.
Find Market by Slug
If you know the exact market slug (from a Polymarket URL), use this for direct lookup:
GET /markets/by-slug?slug={slug}
Example: For URL https://polymarket.com/event/btc-updown-15m-1770129900
curl -H "Authorization: Bearer $LUCKYLOBSTER_API_KEY" \
"https://luckylobster.io/api/agent/v1/markets/by-slug?slug=btc-updown-15m-1770129900"
Response includes clobTokenIds and tokens ready for trading.
Note: For crypto markets, always prefer /markets/crypto over /markets/search — it uses the same deterministic slug lookups as the internal market-data-worker and is far more reliable.
Get Market Details
Get detailed information about a specific market, including token IDs required for market data and trading.
GET /markets/{id}
Parameters:
id: Market ID or condition ID (from search results)
Example:
curl -H "Authorization: Bearer $LUCKYLOBSTER_API_KEY" \
"https://luckylobster.io/api/agent/v1/markets/0x1234..."
Response:
{
"success": true,
"data": {
"id": "1314069",
"conditionId": "0xf46bf33576e8341821161316705ab2357312f58d58b7d157cb8dca73b656b326",
"question": "Bitcoin Up or Down on February 3?",
"outcomes": ["Up", "Down"],
"outcomePrices": ["0.345", "0.655"],
"tokens": [
{"tokenId": "36656454529662513...", "outcome": "Up", "price": "0.345"},
{"tokenId": "10609233133841503...", "outcome": "Down", "price": "0.655"}
],
"clobTokenIds": ["36656454529662513...", "10609233133841503..."],
"volume": "409100.65",
"liquidity": "39255.13",
"active": true,
"acceptingOrders": true,
"spreads": [
{"outcome": "Up", "tokenId": "36656454...", "bid": "0.34", "ask": "0.35", "spread": "0.01"}
]
}
}
Important: Use the tokenId from the tokens array or clobTokenIds for the market data endpoints below.
Market Data Endpoints
These endpoints provide real-time order book and pricing data from the Polymarket CLOB (Central Limit Order Book).
Workflow for getting market data:
- Search markets:
GET /markets/search?q=Bitcoin - Get market details:
GET /markets/{id}→ This returnstokens[].tokenId - Get market data:
GET /orderbook?token_id={tokenId}orGET /market-data?token_id={tokenId}
Get Order Book
Get the order book summary for a token, including all bids and asks.
GET /orderbook?token_id={tokenId}
Parameters:
token_id(required): The outcome token addresstoken_ids(optional): Comma-separated list for batch request (max 20)
Example:
curl -H "Authorization: Bearer $LUCKYLOBSTER_API_KEY" \
"https://luckylobster.io/api/agent/v1/orderbook?token_id=71321045..."
Response:
{
"success": true,
"data": {
"tokenId": "71321045...",
"market": "0xabc...",
"timestamp": "2025-01-15T12:00:00Z",
"bids": [
{"price": "0.65", "size": "1000"},
{"price": "0.64", "size": "500"}
],
"asks": [
{"price": "0.66", "size": "800"},
{"price": "0.67", "size": "1200"}
],
"tickSize": "0.01",
"minOrderSize": "1",
"summary": {
"bidCount": 15,
"askCount": 12,
"bestBid": "0.65",
"bestAsk": "0.66",
"spread": "0.01",
"totalBidSize": "5000.00",
"totalAskSize": "4200.00"
}
}
}
Get Prices
Get current prices for a token including midpoint, buy/sell prices, and last trade.
Real-time data: When you have open positions, the server automatically subscribes to Polymarket WebSocket feeds for those markets. Price data from /prices and /heartbeat will use cached real-time data when available (indicated by "source": "websocket" in the response). This is significantly faster than HTTP polling.
GET /prices?token_id={tokenId}
Parameters:
token_id(required): The outcome token addressside(optional):BUYorSELLto get price for specific sidetoken_ids(optional): Comma-separated list for batch request (max 20)
Example:
curl -H "Authorization: Bearer $LUCKYLOBSTER_API_KEY" \
"https://luckylobster.io/api/agent/v1/prices?token_id=71321045..."
Response:
{
"success": true,
"data": {
"tokenId": "71321045...",
"midpoint": "0.655",
"lastTradePrice": "0.65",
"buyPrice": "0.66",
"sellPrice": "0.65",
"timestamp": "2025-01-15T12:00:00Z",
"source": "websocket"
}
}
Get Spread
Get the bid-ask spread for a token.
GET /spread?token_id={tokenId}
Parameters:
token_id(required): The outcome token addresstoken_ids(optional): Comma-separated list for batch request (max 20)
Example:
curl -H "Authorization: Bearer $LUCKYLOBSTER_API_KEY" \
"https://luckylobster.io/api/agent/v1/spread?token_id=71321045..."
Response:
{
"success": true,
"data": {
"tokenId": "71321045...",
"bid": "0.65",
"ask": "0.66",
"spread": "0.01",
"spreadPercent": "1.52",
"timestamp": "2025-01-15T12:00:00Z"
}
}
Get Comprehensive Market Data
Get all market data in a single request (order book summary, prices, spread).
GET /market-data?token_id={tokenId}
Parameters:
token_id(required): The outcome token address
Example:
curl -H "Authorization: Bearer $LUCKYLOBSTER_API_KEY" \
"https://luckylobster.io/api/agent/v1/market-data?token_id=71321045..."
Response:
{
"success": true,
"data": {
"tokenId": "71321045...",
"prices": {
"midpoint": "0.655",
"bestBid": "0.65",
"bestAsk": "0.66",
"lastTrade": "0.65"
},
"spread": {
"absolute": "0.01",
"percent": "1.52"
},
"orderbook": {
"bidCount": 15,
"askCount": 12,
"totalBidSize": "5000.00",
"totalAskSize": "4200.00",
"topBids": [{"price": "0.65", "size": "1000"}],
"topAsks": [{"price": "0.66", "size": "800"}]
},
"parameters": {
"tickSize": "0.01",
"minOrderSize": "1"
},
"timestamp": "2025-01-15T12:00:00Z"
}
}
Trading Endpoints
Place Order
Place a buy or sell order on a market. Returns real-time order status.
POST /orders
Content-Type: application/json
{
"tokenId": "0x1234...",
"side": "BUY",
"price": 0.65,
"size": 50,
"type": "LIMIT"
}
Parameters:
tokenId: Outcome token address (from market data)side:BUYorSELLprice: Price per share (0.01 to 0.99)size: Number of sharestype:LIMIT,MARKET,FOK, orFAK
Constraints:
- Minimum order amount:
price * sizemust be >= $1.00 USDC - Minimum order size: 5 shares
- Price must be a multiple of 0.01 (tick size)
Order Type Behavior:
MARKET: Fills as much as available at your price or better, kills the rest (recommended for most trades)LIMIT: Rests on the order book until filled or cancelledFOK: Fill-or-Kill — must fill 100% or the entire order is rejected. Use only when you need guaranteed full fills. High failure rate on thin markets.FAK: Fill-and-Kill — same as MARKET
Tip: For short-timeframe markets (5m, 15m) where order books can be thin, prefer MARKET or LIMIT over FOK. MARKET orders will fill whatever is available. LIMIT orders rest on the book and can fill as liquidity arrives.
Real-time Status: The response includes the order's current status from Polymarket. MARKET and FAK orders return faster (~500ms) since they execute immediately. LIMIT orders are checked after ~1 second.
Example:
curl -X POST -H "Authorization: Bearer $LUCKYLOBSTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"tokenId":"0x1234...","side":"BUY","price":0.65,"size":50,"type":"LIMIT"}' \
"https://luckylobster.io/api/agent/v1/orders"
Response (with fill data when available):
{
"success": true,
"data": {
"order": {
"id": "ord_abc123",
"polyOrderId": "0x...",
"status": "FILLED",
"side": "BUY",
"price": 0.65,
"size": 50,
"filledSize": 50,
"avgFillPrice": 0.65,
"transactionHash": "0x...",
"filledAt": "2025-01-15T12:00:01Z"
}
}
}
List Orders
Get your orders with real-time status from Polymarket.
GET /orders?status=OPEN&limit=50
Parameters:
status(optional): Filter by status -PENDING,OPEN,FILLED,PARTIALLY_FILLED,CANCELLED,EXPIRED,FAILEDlimit(optional): Max results (default: 50, max: 100)offset(optional): Pagination offsetsync(optional): Set tofalseto skip live status sync (default: true)
Real-time Sync: Open orders (PENDING, OPEN, PARTIALLY_FILLED) are automatically synced with Polymarket in parallel for real-time status. The response includes sync metadata.
Example:
curl -H "Authorization: Bearer $LUCKYLOBSTER_API_KEY" \
"https://luckylobster.io/api/agent/v1/orders?status=OPEN"
Response includes sync info:
{
"success": true,
"data": [...],
"sync": { "enabled": true, "updated": 2 }
}
Get Order Status
Get details for a specific order, including live status from Polymarket.
GET /orders/{orderId}
Example:
curl -H "Authorization: Bearer $LUCKYLOBSTER_API_KEY" \
"https://luckylobster.io/api/agent/v1/orders/ord_abc123"
Response:
{
"success": true,
"data": {
"order": {
"id": "ord_abc123",
"polyOrderId": "0x...",
"tokenId": "123456...",
"side": "BUY",
"type": "LIMIT",
"price": "0.65",
"size": "50",
"filledSize": "25",
"status": "PARTIALLY_FILLED",
"marketQuestion": "Bitcoin Up or Down?",
"outcome": "Up",
"submittedAt": "2025-01-15T12:00:00Z"
},
"liveStatus": {
"polymarketStatus": "LIVE",
"originalSize": 50,
"sizeMatched": 25,
"price": 0.65
}
}
}
Cancel Order
Cancel an open order. Only orders with status PENDING, OPEN, or PARTIALLY_FILLED can be cancelled.
DELETE /orders/{orderId}
Example:
curl -X DELETE -H "Authorization: Bearer $LUCKYLOBSTER_API_KEY" \
"https://luckylobster.io/api/agent/v1/orders/ord_abc123"
Response:
{
"success": true,
"message": "Order cancelled successfully",
"data": {
"order": {
"id": "ord_abc123",
"polyOrderId": "0x...",
"status": "CANCELLED",
"previousStatus": "OPEN",
"filledSize": "25",
"cancelledAt": "2025-01-15T12:05:00Z"
}
}
}
Error Responses:
400: Order cannot be cancelled (already filled, cancelled, or failed)403: Order was not placed by your agent404: Order not found
Notes:
- You can only cancel orders that your agent placed
- If an order is partially filled, cancelling stops further fills but keeps the filled portion
- The
previousStatusfield shows what status the order had before cancellation
Close Position (One-Shot)
Close an entire position with a single API call. The server handles determining the correct side, fetching current price, and placing the market order.
POST /positions/{positionId}/close
URL Parameters:
positionId: Position ID fromGET /positions
Optional Body:
{
"type": "MARKET", // Order type: "MARKET" (default), "FOK", or "LIMIT"
"slippage": 0.02, // Max slippage for LIMIT orders (default: 2%)
"dryRun": true // Preview without executing
}
Example - Close a position:
curl -X POST -H "Authorization: Bearer $LUCKYLOBSTER_API_KEY" \
"https://luckylobster.io/api/agent/v1/positions/pos_abc123/close"
Example - Preview first (dry run):
curl -X POST -H "Authorization: Bearer $LUCKYLOBSTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"dryRun": true}' \
"https://luckylobster.io/api/agent/v1/positions/pos_abc123/close"
Response:
{
"success": true,
"message": "Position closed successfully",
"data": {
"order": {
"id": "ord_xyz789",
"polyOrderId": "0x...",
"status": "FILLED",
"side": "SELL",
"type": "MARKET",
"price": 0.65,
"size": 100,
"filledSize": 100,
"avgFillPrice": 0.65,
"transactionHash": "0x..."
},
"position": {
"id": "pos_abc123",
"remainingSize": 0,
"isClosed": true
},
"execution": {
"proceeds": 65.00,
"pnl": 10.00,
"pnlPercent": 18.18
},
"market": {
"slug": "bitcoin-up-or-down-on-february-3",
"question": "Bitcoin Up or Down on February 3?",
"outcome": "Up"
}
}
}
Dry Run Response:
{
"success": true,
"dryRun": true,
"message": "Position close preview - no order placed",
"data": {
"position": {
"id": "pos_abc123",
"tokenId": "123456...",
"size": 100,
"avgEntryPrice": 0.55
},
"closeOrder": {
"side": "SELL",
"type": "MARKET",
"price": 0.65,
"size": 100
},
"estimates": {
"currentPrice": 0.65,
"bidPrice": 0.65,
"proceeds": 65.00,
"pnl": 10.00,
"pnlPercent": 18.18
}
}
}
Error Responses:
400: Position is already closed (size=0) or already settled403: Position belongs to another user404: Position not found503: Unable to fetch market price (market may be closed/illiquid)
Notes:
- Uses the current bid price for immediate execution
- For LIMIT orders, applies slippage tolerance (default 2%) below bid
- Position is partially closed if order only partially fills
- Check
position.isClosedto verify complete exit
Get Balance
Get raw wallet balance (live from chain).
GET /balance
Response:
{
"success": true,
"data": {
"usdc": 93.16,
"matic": 0.5,
"address": "0x1234...",
"walletType": "proxy"
}
}
Fields:
usdc: Raw USDC in walletmatic: For gas (rarely needed)address: Your trading wallet on Polygon
Approve Tokens (Fix "not enough allowance" errors)
If you get a "not enough balance / allowance" error when selling or closing positions, you need to approve the CTF (Conditional Token Framework) contract. This is a one-time setup per wallet.
POST /wallet/approve
Request Body:
{
"token": "CTF" // or "USDC", "NEG_RISK", "all"
}
Token Types:
USDC: Required for buying (usually already approved)CTF: Required for selling/closing positionsNEG_RISK: Required for multi-outcome marketsall: Approve all tokens at once
Example - Fix selling errors:
curl -X POST -H "Authorization: Bearer $LUCKYLOBSTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"token": "CTF"}' \
"https://luckylobster.io/api/agent/v1/wallet/approve"
Response:
{
"success": true,
"message": "CTF approved successfully",
"data": {
"approvals": { "CTF": "0x..." },
"successful": ["CTF"],
"failed": []
}
}
When to use:
- Error: "not enough balance / allowance" when selling
- Error: "not enough balance / allowance" when closing a position
- First time selling after wallet setup
Get Budget
Get how much you can spend. Use this before placing orders.
Budget = min(wallet balance, fixed limit, % of wallet)
GET /budget
Response:
{
"success": true,
"data": {
"usdc": 46.58,
"limitedBy": "percent",
"wallet": 93.16,
"config": {
"fixedLimit": null,
"budgetPercent": 50,
"maxPositionValue": null,
"used": 0
}
}
}
Fields:
usdc: What you can spend (accounts for all limits)limitedBy: Why you're capped ("wallet","fixed_limit","percent","position_limit")wallet: Raw wallet balanceconfig: Your budget settings
Get Positions
Get your current positions directly from Polymarket. The endpoint fetches from the Polymarket Data API (source of truth) with automatic fallback to CLOB trades if Data API returns empty.
GET /positions
Parameters:
status(optional): Filter by status -"open"(default),"settled","redeemable", or"all"token_id(optional): Filter by specific token IDcondition_id(optional): Filter by condition ID (market)source(optional): Force data source -"clob"to bypass Data API and fetch directly from CLOB trades
Example - Get Open Positions:
curl -H "Authorization: Bearer $LUCKYLOBSTER_API_KEY" \
"https://luckylobster.io/api/agent/v1/positions"
Example - Get Redeemable Positions:
curl -H "Authorization: Bearer $LUCKYLOBSTER_API_KEY" \
"https://luckylobster.io/api/agent/v1/positions?status=redeemable"
Example - Force CLOB Source (for freshest data):
curl -H "Authorization: Bearer $LUCKYLOBSTER_API_KEY" \
"https://luckylobster.io/api/agent/v1/positions?source=clob"
Response:
{
"success": true,
"data": {
"positions": [
{
"id": "0xabc123_0",
"tokenId": "12345...",
"conditionId": "0xabc123...",
"market": {
"slug": "bitcoin-up-or-down-on-february-3",
"question": "Bitcoin Up or Down on February 3?",
"outcome": "Up",
"endDate": "2026-02-03T17:00:00Z",
"eventSlug": "btc-updown"
},
"size": 100.0,
"avgEntryPrice": 0.55,
"currentPrice": 0.62,
"currentValue": 62.00,
"pnl": {
"unrealized": 7.00,
"unrealizedPercent": 12.73,
"realized": 0.00,
"realizedPercent": 0.00
},
"status": {
"isOpen": true,
"isSettled": false,
"isRedeemable": false,
"isMergeable": false,
"isNegRisk": false
},
"oppositeOutcome": "Down",
"oppositeAsset": "67890...",
"updatedAt": "2026-02-03T14:45:00.000Z"
}
],
"summary": {
"totalPositions": 1,
"totalUnrealizedPnl": 7.00,
"totalRealizedPnl": 0.00,
"totalValue": 62.00
},
"filters": {
"status": "open",
"tokenId": null,
"conditionId": null
},
"wallet": {
"address": "0x539b2de928064898...",
"type": "proxy"
},
"source": "data-api"
}
}
Key Fields:
size: Number of outcome tokens heldavgEntryPrice: Average price paid per token (0.00 to 1.00)currentPrice: Live price from PolymarketcurrentValue: Current value in USDCpnl.unrealized: Unrealized profit/losspnl.unrealizedPercent: Unrealized P&L as percentagestatus.isRedeemable:trueif market resolved and position can be redeemedstatus.isNegRisk:truefor multi-outcome markets (require special redemption)wallet.type:"proxy"(Polymarket smart wallet) or"eoa"(direct wallet)source:"data-api"or"clob-trades"- shows which data source was used
Data Source Behavior:
- Default: Fetches from Polymarket Data API (most reliable, includes all historical positions)
- Fallback: If Data API returns empty, automatically falls back to CLOB trades
- Forced CLOB: Use
?source=clobfor freshest data immediately after placing an order (Data API can have ~30s delay)
When to use source=clob:
- Right after placing an order (Data API has indexing delay)
- When Data API returns fewer positions than expected
- For debugging position discrepancies
Settlement & Redemption
When a market resolves, winning outcome tokens can be redeemed for $1.00 USDC each. The redemption endpoint automatically fetches all redeemable positions from Polymarket and redeems them in a single batched transaction.
List Redeemable Positions
Check what positions are ready for redemption.
GET /settlements/redeem
Response:
{
"success": true,
"data": {
"positions": [
{
"conditionId": "0xbc13af0a940bb9a...",
"title": "Bitcoin Up or Down - February 4, 1:45PM-2:00PM ET",
"outcome": "Down",
"size": 5.0,
"estimatedValue": "$5.00",
"negRisk": false
}
],
"count": 3,
"totalValue": "$42.50",
"wallet": "0x539b2de928064898..."
},
"message": "Found 3 redeemable positions (~$42.50). POST to redeem."
}
Redeem Positions
Redeem winning positions in a single batched transaction. You can redeem all positions or target specific ones.
POST /settlements/redeem
Optional Parameters:
{
"conditionId": "0x...", // Redeem ONLY this specific position
"conditionIds": ["0x...", "..."], // Redeem ONLY these specific positions
"limit": 50, // Max positions to redeem (default: 10, max: 50)
"minValue": 1.00, // Skip positions below this value (default: $0.10)
"dryRun": true // Preview what would be redeemed without executing
}
Example - Redeem a specific position:
curl -X POST -H "X-API-Key: $LUCKYLOBSTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"conditionId": "0xbc13af0a940bb9a..."}' \
"https://luckylobster.io/api/agent/v1/settlements/redeem"
Example - Redeem all:
curl -X POST -H "X-API-Key: $LUCKYLOBSTER_API_KEY" \
"https://luckylobster.io/api/agent/v1/settlements/redeem"
Example - Dry run first:
curl -X POST -H "X-API-Key: $LUCKYLOBSTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"dryRun": true}' \
"https://luckylobster.io/api/agent/v1/settlements/redeem"
Example - Redeem up to 50, skip dust:
curl -X POST -H "X-API-Key: $LUCKYLOBSTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"limit": 50, "minValue": 1.00}' \
"https://luckylobster.io/api/agent/v1/settlements/redeem"
Response:
{
"success": true,
"message": "Redeemed 3 positions (~$42.50)",
"data": {
"processed": 3,
"redeemed": [
{
"conditionId": "0xbc13af0a...",
"title": "Bitcoin Up or Down - February 4, 1:45PM-2:00PM ET",
"outcome": "Down",
"size": 5.0,
"txHash": "0x82d8d7e4d63185..."
}
],
"failed": [],
"remaining": 0,
"totalValueRedeemed": "$42.50"
}
}
Error Responses:
404: Wallet not found403: Missing "redeem" permission501: Polymarket Builder API not configured
Notes:
- Redemption is gasless (executed via Polymarket relayer)
- All positions are batched into a single on-chain transaction for efficiency
- Only positions marked as "redeemable" by Polymarket are included
- Both standard and NegRisk markets are handled automatically
Heartbeat (Status Check)
The heartbeat endpoint provides a single-call summary of your portfolio, pending actions, and account status. Call it periodically to stay informed.
Check Heartbeat
GET /heartbeat?skill_version=10
Include skill_version so the server can indicate if a newer version is available.
Returns aggregated data: open positions, redeemable positions, filled orders since last check, budget status, and items that may need attention.
Response:
{
"success": true,
"data": {
"status": "ACTION_NEEDED",
"timestamp": "2026-02-06T15:30:00Z",
"actions": [
{
"type": "REDEEM",
"priority": "high",
"summary": "2 positions ready to redeem (~$42.50)",
"details": { "positions": [...], "action": "POST /settlements/redeem" }
},
{
"type": "ORDER_FILLED",
"priority": "medium",
"summary": "3 order(s) filled since last check",
"details": { "fills": [...], "totalPnl": 12.50 }
}
],
"portfolio": {
"openPositions": 5,
"totalValue": 250.00,
"unrealizedPnl": 12.50,
"redeemableCount": 2,
"redeemableValue": 42.50
},
"orderActivity": {
"openOrders": 1,
"filledSinceLastHeartbeat": 3,
"recentFills": [...]
},
"budget": {
"available": 46.58,
"limitedBy": "percent",
"walletBalance": 93.16
},
"heartbeat": {
"next_check_at": "2026-02-06T16:00:00Z",
"interval_ms": 1800000,
"active_hours": { "start": "09:00", "end": "22:00", "timezone": "America/New_York" },
"heartbeat_count": 42,
"latest_skill_version": 10
},
"realtime": {
"subscribedMarkets": 3,
"clobConnected": true,
"sportsConnected": false,
"cryptoConnected": true
}
}
}
Status Values:
ACTION_NEEDED: Items may need attention. Check theactionsarray.OK: Nothing needs attention.SLEEPING: Outside configured active hours.
Action Types:
REDEEM(high): Settled positions ready for redemption. CallPOST /settlements/redeem.ORDER_FILLED(medium): Orders filled since last heartbeat. Includes P&L details.BUDGET_LOW(medium): Budget running low.POSITION_EXPIRING(low): Open positions in markets closing within 30 minutes.SEEK_TRADES(low): Budget is available. Trading opportunities may exist — useGET /markets/searchorGET /markets/cryptoto browse.
Heartbeat Scheduling:
The response includes heartbeat.next_check_at as a suggested time for your next call, and heartbeat.latest_skill_version so you can check whether a newer skill version is available on ClawHub. Use the suggested interval or your own preferred schedule.
Autonomous Strategies
Create server-side trading strategies that execute automatically. Instead of making trade decisions on every heartbeat (which costs tokens), define rules once and let the server trade for you.
Strategy Types
PRICE_ALERT - Buy or sell when price hits a target (stop-loss, take-profit, limit buy) RECURRING_BUY - Dollar-cost average into a market at fixed intervals BUY_LOW_SELL_HIGH - Buy below a floor, sell above a ceiling, repeat
Create Strategy
POST ${baseUrl}/api/agent/v1/strategies
Authorization: Bearer {api_key}
// PRICE_ALERT example: Sell if price drops below 0.35
{
"name": "BTC Stop-Loss",
"type": "PRICE_ALERT",
"config": {
"marketQuery": "bitcoin",
"outcome": "Yes",
"side": "SELL",
"triggerCondition": "PRICE_LTE",
"triggerPrice": 0.35,
"size": 100,
"orderType": "MARKET"
},
"maxBudget": 50
}
// RECURRING_BUY example: Buy $10 of Bitcoin every hour
{
"name": "BTC Recurring Hourly",
"type": "RECURRING_BUY",
"config": {
"marketQuery": "bitcoin",
"outcome": "Yes",
"amountPerInterval": 10,
"interval": "1h",
"maxTotalAmount": 200,
"priceLimit": 0.70
},
"maxBudget": 200
}
// BUY_LOW_SELL_HIGH example: Buy below 0.40, sell above 0.60
{
"name": "BTC Range Trader",
"type": "BUY_LOW_SELL_HIGH",
"config": {
"marketQuery": "bitcoin",
"outcome": "Yes",
"buyBelow": 0.40,
"sellAbove": 0.60,
"sizePerTrade": 50,
"maxOpenSize": 200
},
"maxBudget": 500
}
// COPY_TRADE example: Mirror a wallet's trades with $10 per copy
{
"name": "Copy Whale",
"type": "COPY_TRADE",
"config": {
"targetAddress": "0x1234567890abcdef1234567890abcdef12345678",
"sizingMode": "fixed",
"fixedAmount": 10,
"copySells": true,
"maxPositionSize": 500
},
"maxBudget": 500
}
// COPY_TRADE proportional example: Copy 50% of target's trade size
{
"name": "Mirror Trader",
"type": "COPY_TRADE",
"config": {
"targetAddress": "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd",
"sizingMode": "proportional",
"proportionPct": 50,
"copySells": true
},
"maxBudget": 1000
}
COPY_TRADE Config Fields
| Field | Required | Description |
|---|---|---|
targetAddress | Yes | Wallet address to copy (0x + 40 hex chars) |
sizingMode | Yes | "fixed" (fixed USDC per trade) or "proportional" (% of target's size) |
fixedAmount | When fixed | USDC to spend per copy trade |
proportionPct | When proportional | 1-100, percentage of target's trade size |
copySells | Yes | true to also copy sell trades, false for buys only |
maxPositionSize | No | Max shares to hold per token |
tokenFilter | No | Array of token IDs — only copy trades for these tokens |
Copy trading monitors the Polygon blockchain in real-time (~2 second detection). It cannot copy your own wallet.
List Strategies
GET ${baseUrl}/api/agent/v1/strategies
GET ${baseUrl}/api/agent/v1/strategies?status=ACTIVE&type=DCA
Get Strategy Details
GET ${baseUrl}/api/agent/v1/strategies/{id}
Returns full strategy with last 20 execution records.
Update Strategy
PATCH ${baseUrl}/api/agent/v1/strategies/{id}
{ "config": { ... }, "maxBudget": 300 }
Pause / Resume / Cancel
POST ${baseUrl}/api/agent/v1/strategies/{id}/pause
POST ${baseUrl}/api/agent/v1/strategies/{id}/resume
DELETE ${baseUrl}/api/agent/v1/strategies/{id}
Strategy Lifecycle
- ACTIVE - Server evaluates every ~10 seconds
- PAUSED - Paused by user (from dashboard) or agent. Not evaluated until resumed.
- ERROR - Auto-paused after 3 consecutive failures. Use
POST /strategies/{id}/resumeto retry. - COMPLETED - Budget exhausted or one-shot trigger fired
- CANCELLED - Cancelled by user (from dashboard) or agent. Cannot be resumed.
- EXPIRED - Past 24-hour default TTL (or custom
expiresAt). Cannot be resumed.
Crypto Market Auto-Discovery
For strategies using marketQuery instead of tokenId: the server automatically discovers the current active market each evaluation. For known crypto assets (btc, eth, sol, xrp, etc.), this uses deterministic slug-based lookups — the same approach as the market-data-worker. This reliably handles Polymarket's ephemeral crypto markets (15-min, hourly, daily) that expire and are replaced. Non-crypto queries fall back to text search.
COPY_TRADE Real-Time Monitoring
Copy trade strategies use blockchain event monitoring (not polling) to detect target wallet activity in ~2 seconds. The server watches ERC1155 transfer events on Polymarket's CTF contract via Alchemy WebSocket RPC. Events are deduplicated, so reconnections don't cause double-execution.
Heartbeat Integration
The heartbeat response includes a strategies section and these action types:
- STRATEGY_EXECUTED (medium) — Trades placed by your strategies
- STRATEGY_ERROR (high) — Strategies auto-paused after consecutive errors
- STRATEGY_COMPLETED (low) — Strategies that finished (budget exhausted or trigger fired)
- STRATEGY_PAUSED (high) — Strategy paused by the user from the dashboard.
POST /strategies/{id}/resumeto restart. - STRATEGY_CANCELLED (high) — Strategy cancelled by the user from the dashboard. Create a new strategy if needed.
Best Practices
- Set maxBudget on every strategy to limit exposure
- Use PRICE_ALERT for stop-loss/take-profit on existing positions
- Use RECURRING_BUY with marketQuery for crypto markets (handles market expiry)
- Review heartbeat periodically to see strategy execution results
- Max 10 active strategies per agent
Error Handling
{
"success": false,
"error": "Error Type",
"message": "Human-readable message"
}
Status Codes:
401: Invalid API key403: Insufficient permissions or budget exceeded404: Resource not found429: Rate limit exceeded
Permissions
read: View markets, orders, positions, balancetrade: Place orderscancel: Cancel ordersredeem: Redeem settled positions