{"skill":{"slug":"luckylobster-skill","displayName":"LuckyLobster","summary":"Trade prediction markets on Polymarket. Search markets, place orders, and manage positions.","description":"---\nname: luckylobster\ndescription: Trade prediction markets on Polymarket. Search markets, place orders, and manage positions.\nhomepage: https://luckylobster.io\nuser-invocable: true\nmetadata: {\"openclaw\":{\"version\":10,\"primaryEnv\":\"LUCKYLOBSTER_API_KEY\",\"emoji\":\"🦞\",\"homepage\":\"https://luckylobster.io\",\"requires\":{\"env\":[\"LUCKYLOBSTER_API_KEY\"]}}}\n---\n\n# LuckyLobster - Polymarket Trading API\n\nTrade prediction markets on Polymarket through a secure API designed for AI agents.\n\n## How Polymarket Works\n\nPolymarket is a prediction market where you trade on the outcomes of real-world events.\n\n**Buying Contracts:**\n- In active markets, you can buy outcome contracts priced from $0.01 to $0.99\n- Each contract entitles you to 1 share at your purchase price\n- Lower prices = higher potential return, but less likely outcome (market's view)\n\n**Selling Contracts:**\n- You can sell your shares at any time before the market closes\n- Sell price depends on current market conditions\n\n**Market Resolution:**\n- When a market resolves, the winning outcome pays **$1.00 USDC per share**\n- Losing outcomes pay $0 (or a negligible amount in rare cases)\n\n**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.\n\n## Setup\n\nIf you don't have an API key configured, use the device authorization flow to link your account.\n\n### Device Authorization Flow\n\n**Step 1: Request a Device Code**\n\n```http\nPOST https://luckylobster.io/api/auth/device\nContent-Type: application/json\n\n{\n  \"agent_name\": \"OpenClaw Agent\"\n}\n```\n\nResponse:\n```json\n{\n  \"device_code\": \"abc123...\",\n  \"user_code\": \"ABCD-1234\",\n  \"verification_uri\": \"https://luckylobster.io/link\",\n  \"verification_uri_complete\": \"https://luckylobster.io/link?code=ABCD-1234\",\n  \"expires_in\": 900,\n  \"interval\": 5\n}\n```\n\n**Step 2: Direct the User**\n\nParse the JSON response and extract the `verification_uri_complete` field. Display it to the user as a clickable link:\n\n```\n🦞 To connect LuckyLobster, click: {verification_uri_complete}\n```\n\n**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.\n\n**Step 3: Poll for Authorization**\n\nPoll every 5 seconds until authorized:\n\n```http\nGET https://luckylobster.io/api/auth/device/token?device_code=abc123...\n```\n\nPending response:\n```json\n{ \"error\": \"authorization_pending\" }\n```\n\nSuccess response:\n```json\n{\n  \"api_key\": \"ll_abc123...\",\n  \"user_email\": \"user@example.com\",\n  \"permissions\": [\"read\", \"trade\", \"cancel\", \"redeem\"]\n}\n```\n\nAll linked agents receive standard permissions: **read** (view markets/orders/positions), **trade** (buy/sell), **cancel** (cancel orders), and **redeem** (settle positions).\n\n**Step 4: Store the API Key**\n\nSave the API key persistently so it survives restarts. It is only returned once.\n\nUse the `gateway` tool with `config.patch` to save it in the skill config:\n\n```javascript\ngateway.config.patch({\n  patch: {\n    skills: {\n      entries: {\n        luckylobster: {\n          env: {\n            LUCKYLOBSTER_API_KEY: \"ll_abc123...\"\n          }\n        }\n      }\n    }\n  }\n})\n```\n\n---\n\n## Authentication\n\nAll API requests require an API key in the Authorization header:\n\n```\nAuthorization: Bearer YOUR_API_KEY\n```\n\n## Base URL\n\n```\nhttps://luckylobster.io/api/agent/v1\n```\n\n## Rate Limits\n\n- Default: 100 requests per minute\n- Rate limit headers included in responses:\n  - `X-RateLimit-Limit`: Max requests allowed\n  - `X-RateLimit-Remaining`: Requests remaining\n  - `X-RateLimit-Reset`: Reset time (ISO 8601)\n\n## Endpoints\n\n### Search Markets\n\nFind prediction markets on Polymarket. The search uses smart relevance scoring to return the best matches first.\n\n```http\nGET /markets/search?q={query}\n```\n\n**Parameters:**\n- `q` (required for search): Natural language query - \"bitcoin 15m\", \"trump election\", \"superbowl winner\"\n- `limit` (optional): Max results (default: 10, max: 100)\n- `offset` (optional): Pagination offset\n- `sort` (optional): \"relevance\" (default), \"volume\", \"liquidity\", \"end_date\", \"recent\"\n- `ending_soon` (optional): Prioritize markets ending within 24h (default: false)\n- `min_volume` (optional): Minimum volume in USD (default: 100)\n- `min_liquidity` (optional): Minimum liquidity in USD\n- `tag` (optional): Filter by category: \"crypto\", \"politics\", \"sports\", \"entertainment\"\n- `accepting_orders` (optional): Only tradeable markets (default: true)\n\n**Search Tips:**\n- **Shorthand supported:** \"btc 15m\" → \"Bitcoin Up or Down\", \"eth daily\" → \"Ethereum Up or Down on\"\n- The search auto-expands: btc→Bitcoin, eth→Ethereum, sol→Solana, etc.\n- Time keywords (15m, hourly, daily) auto-expand to \"Up or Down\" queries\n- Results are ranked by relevance: query match + liquidity + volume + accepting orders\n- For time-sensitive markets, add `ending_soon=true` to prioritize markets expiring within 24h\n- First result is usually the best match - check `context.topMatch`\n\n**Example - Find Current BTC Market:**\n```bash\ncurl -H \"Authorization: Bearer $LUCKYLOBSTER_API_KEY\" \\\n  \"https://luckylobster.io/api/agent/v1/markets/search?q=bitcoin%20up%20down&ending_soon=true&limit=5\"\n```\n\n**Example - High-Volume Politics Markets:**\n```bash\ncurl -H \"Authorization: Bearer $LUCKYLOBSTER_API_KEY\" \\\n  \"https://luckylobster.io/api/agent/v1/markets/search?q=election&tag=politics&sort=volume\"\n```\n\n**Response:**\n```json\n{\n  \"success\": true,\n  \"data\": [\n    {\n      \"id\": \"1314069\",\n      \"slug\": \"bitcoin-up-or-down-on-february-3\",\n      \"question\": \"Bitcoin Up or Down on February 3?\",\n      \"outcomes\": [\"Up\", \"Down\"],\n      \"outcomePrices\": [\"0.65\", \"0.35\"],\n      \"volume\": \"409100.65\",\n      \"liquidity\": \"39255.13\",\n      \"endDate\": \"2026-02-03T17:00:00Z\",\n      \"active\": true,\n      \"acceptingOrders\": true\n    }\n  ],\n  \"pagination\": { \"limit\": 5, \"offset\": 0, \"count\": 1, \"hasMore\": false },\n  \"context\": {\n    \"hasResults\": true,\n    \"topMatch\": { \"id\": \"1314069\", \"question\": \"Bitcoin Up or Down on February 3?\", \"acceptingOrders\": true },\n    \"endingSoonCount\": 1\n  },\n  \"options\": {\n    \"sortBy\": [\"relevance\", \"volume\", \"liquidity\", \"end_date\", \"recent\"],\n    \"tags\": [\"crypto\", \"politics\", \"sports\", \"entertainment\"]\n  }\n}\n```\n\n**Workflow for Trading:**\n1. Search: `GET /markets/search?q=bitcoin up down`\n2. Use the `id` from the top result to get full details: `GET /markets/{id}`\n3. Response includes `clobTokenIds` - use these with trading endpoints\n\n---\n\n### Quick Crypto Market Lookup\n\nFor 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:\n\n```http\nGET /markets/crypto?asset={btc|eth|sol|xrp|doge|matic}&timeframe={daily|hourly|15m}\n```\n\n**Examples:**\n- `/markets/crypto?asset=btc` - Today's Bitcoin daily market\n- `/markets/crypto?asset=btc&timeframe=15m` - Current Bitcoin 15-minute market\n- `/markets/crypto?asset=eth&timeframe=hourly` - Current Ethereum hourly market\n- `/markets/crypto?asset=xrp&timeframe=15m` - Current XRP 15-minute market\n\n**Response includes `tokens` array with `tokenId`, `negRisk`, and live spread data ready for trading.**\n\n---\n\n### Find Market by Slug\n\nIf you know the exact market slug (from a Polymarket URL), use this for direct lookup:\n\n```http\nGET /markets/by-slug?slug={slug}\n```\n\n**Example:** For URL `https://polymarket.com/event/btc-updown-15m-1770129900`\n```bash\ncurl -H \"Authorization: Bearer $LUCKYLOBSTER_API_KEY\" \\\n  \"https://luckylobster.io/api/agent/v1/markets/by-slug?slug=btc-updown-15m-1770129900\"\n```\n\nResponse includes `clobTokenIds` and `tokens` ready for trading.\n\n**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.\n\n### Get Market Details\n\nGet detailed information about a specific market, **including token IDs required for market data and trading**.\n\n```http\nGET /markets/{id}\n```\n\n**Parameters:**\n- `id`: Market ID or condition ID (from search results)\n\n**Example:**\n```bash\ncurl -H \"Authorization: Bearer $LUCKYLOBSTER_API_KEY\" \\\n  \"https://luckylobster.io/api/agent/v1/markets/0x1234...\"\n```\n\n**Response:**\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"id\": \"1314069\",\n    \"conditionId\": \"0xf46bf33576e8341821161316705ab2357312f58d58b7d157cb8dca73b656b326\",\n    \"question\": \"Bitcoin Up or Down on February 3?\",\n    \"outcomes\": [\"Up\", \"Down\"],\n    \"outcomePrices\": [\"0.345\", \"0.655\"],\n    \"tokens\": [\n      {\"tokenId\": \"36656454529662513...\", \"outcome\": \"Up\", \"price\": \"0.345\"},\n      {\"tokenId\": \"10609233133841503...\", \"outcome\": \"Down\", \"price\": \"0.655\"}\n    ],\n    \"clobTokenIds\": [\"36656454529662513...\", \"10609233133841503...\"],\n    \"volume\": \"409100.65\",\n    \"liquidity\": \"39255.13\",\n    \"active\": true,\n    \"acceptingOrders\": true,\n    \"spreads\": [\n      {\"outcome\": \"Up\", \"tokenId\": \"36656454...\", \"bid\": \"0.34\", \"ask\": \"0.35\", \"spread\": \"0.01\"}\n    ]\n  }\n}\n```\n\n**Important:** Use the `tokenId` from the `tokens` array or `clobTokenIds` for the market data endpoints below.\n\n---\n\n## Market Data Endpoints\n\nThese endpoints provide real-time order book and pricing data from the Polymarket CLOB (Central Limit Order Book).\n\n**Workflow for getting market data:**\n1. Search markets: `GET /markets/search?q=Bitcoin`\n2. Get market details: `GET /markets/{id}` → This returns `tokens[].tokenId`\n3. Get market data: `GET /orderbook?token_id={tokenId}` or `GET /market-data?token_id={tokenId}`\n\n### Get Order Book\n\nGet the order book summary for a token, including all bids and asks.\n\n```http\nGET /orderbook?token_id={tokenId}\n```\n\n**Parameters:**\n- `token_id` (required): The outcome token address\n- `token_ids` (optional): Comma-separated list for batch request (max 20)\n\n**Example:**\n```bash\ncurl -H \"Authorization: Bearer $LUCKYLOBSTER_API_KEY\" \\\n  \"https://luckylobster.io/api/agent/v1/orderbook?token_id=71321045...\"\n```\n\n**Response:**\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"tokenId\": \"71321045...\",\n    \"market\": \"0xabc...\",\n    \"timestamp\": \"2025-01-15T12:00:00Z\",\n    \"bids\": [\n      {\"price\": \"0.65\", \"size\": \"1000\"},\n      {\"price\": \"0.64\", \"size\": \"500\"}\n    ],\n    \"asks\": [\n      {\"price\": \"0.66\", \"size\": \"800\"},\n      {\"price\": \"0.67\", \"size\": \"1200\"}\n    ],\n    \"tickSize\": \"0.01\",\n    \"minOrderSize\": \"1\",\n    \"summary\": {\n      \"bidCount\": 15,\n      \"askCount\": 12,\n      \"bestBid\": \"0.65\",\n      \"bestAsk\": \"0.66\",\n      \"spread\": \"0.01\",\n      \"totalBidSize\": \"5000.00\",\n      \"totalAskSize\": \"4200.00\"\n    }\n  }\n}\n```\n\n### Get Prices\n\nGet current prices for a token including midpoint, buy/sell prices, and last trade.\n\n**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.\n\n```http\nGET /prices?token_id={tokenId}\n```\n\n**Parameters:**\n- `token_id` (required): The outcome token address\n- `side` (optional): `BUY` or `SELL` to get price for specific side\n- `token_ids` (optional): Comma-separated list for batch request (max 20)\n\n**Example:**\n```bash\ncurl -H \"Authorization: Bearer $LUCKYLOBSTER_API_KEY\" \\\n  \"https://luckylobster.io/api/agent/v1/prices?token_id=71321045...\"\n```\n\n**Response:**\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"tokenId\": \"71321045...\",\n    \"midpoint\": \"0.655\",\n    \"lastTradePrice\": \"0.65\",\n    \"buyPrice\": \"0.66\",\n    \"sellPrice\": \"0.65\",\n    \"timestamp\": \"2025-01-15T12:00:00Z\",\n    \"source\": \"websocket\"\n  }\n}\n```\n\n### Get Spread\n\nGet the bid-ask spread for a token.\n\n```http\nGET /spread?token_id={tokenId}\n```\n\n**Parameters:**\n- `token_id` (required): The outcome token address\n- `token_ids` (optional): Comma-separated list for batch request (max 20)\n\n**Example:**\n```bash\ncurl -H \"Authorization: Bearer $LUCKYLOBSTER_API_KEY\" \\\n  \"https://luckylobster.io/api/agent/v1/spread?token_id=71321045...\"\n```\n\n**Response:**\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"tokenId\": \"71321045...\",\n    \"bid\": \"0.65\",\n    \"ask\": \"0.66\",\n    \"spread\": \"0.01\",\n    \"spreadPercent\": \"1.52\",\n    \"timestamp\": \"2025-01-15T12:00:00Z\"\n  }\n}\n```\n\n### Get Comprehensive Market Data\n\nGet all market data in a single request (order book summary, prices, spread).\n\n```http\nGET /market-data?token_id={tokenId}\n```\n\n**Parameters:**\n- `token_id` (required): The outcome token address\n\n**Example:**\n```bash\ncurl -H \"Authorization: Bearer $LUCKYLOBSTER_API_KEY\" \\\n  \"https://luckylobster.io/api/agent/v1/market-data?token_id=71321045...\"\n```\n\n**Response:**\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"tokenId\": \"71321045...\",\n    \"prices\": {\n      \"midpoint\": \"0.655\",\n      \"bestBid\": \"0.65\",\n      \"bestAsk\": \"0.66\",\n      \"lastTrade\": \"0.65\"\n    },\n    \"spread\": {\n      \"absolute\": \"0.01\",\n      \"percent\": \"1.52\"\n    },\n    \"orderbook\": {\n      \"bidCount\": 15,\n      \"askCount\": 12,\n      \"totalBidSize\": \"5000.00\",\n      \"totalAskSize\": \"4200.00\",\n      \"topBids\": [{\"price\": \"0.65\", \"size\": \"1000\"}],\n      \"topAsks\": [{\"price\": \"0.66\", \"size\": \"800\"}]\n    },\n    \"parameters\": {\n      \"tickSize\": \"0.01\",\n      \"minOrderSize\": \"1\"\n    },\n    \"timestamp\": \"2025-01-15T12:00:00Z\"\n  }\n}\n```\n\n---\n\n## Trading Endpoints\n\n### Place Order\n\nPlace a buy or sell order on a market. Returns real-time order status.\n\n```http\nPOST /orders\nContent-Type: application/json\n\n{\n  \"tokenId\": \"0x1234...\",\n  \"side\": \"BUY\",\n  \"price\": 0.65,\n  \"size\": 50,\n  \"type\": \"LIMIT\"\n}\n```\n\n**Parameters:**\n- `tokenId`: Outcome token address (from market data)\n- `side`: `BUY` or `SELL`\n- `price`: Price per share (0.01 to 0.99)\n- `size`: Number of shares\n- `type`: `LIMIT`, `MARKET`, `FOK`, or `FAK`\n\n**Constraints:**\n- Minimum order amount: `price * size` must be >= $1.00 USDC\n- Minimum order size: 5 shares\n- Price must be a multiple of 0.01 (tick size)\n\n**Order Type Behavior:**\n- `MARKET`: Fills as much as available at your price or better, kills the rest (recommended for most trades)\n- `LIMIT`: Rests on the order book until filled or cancelled\n- `FOK`: 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.\n- `FAK`: Fill-and-Kill — same as MARKET\n\n**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.\n\n**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.\n\n**Example:**\n```bash\ncurl -X POST -H \"Authorization: Bearer $LUCKYLOBSTER_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"tokenId\":\"0x1234...\",\"side\":\"BUY\",\"price\":0.65,\"size\":50,\"type\":\"LIMIT\"}' \\\n  \"https://luckylobster.io/api/agent/v1/orders\"\n```\n\n**Response (with fill data when available):**\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"order\": {\n      \"id\": \"ord_abc123\",\n      \"polyOrderId\": \"0x...\",\n      \"status\": \"FILLED\",\n      \"side\": \"BUY\",\n      \"price\": 0.65,\n      \"size\": 50,\n      \"filledSize\": 50,\n      \"avgFillPrice\": 0.65,\n      \"transactionHash\": \"0x...\",\n      \"filledAt\": \"2025-01-15T12:00:01Z\"\n    }\n  }\n}\n```\n\n### List Orders\n\nGet your orders with real-time status from Polymarket.\n\n```http\nGET /orders?status=OPEN&limit=50\n```\n\n**Parameters:**\n- `status` (optional): Filter by status - `PENDING`, `OPEN`, `FILLED`, `PARTIALLY_FILLED`, `CANCELLED`, `EXPIRED`, `FAILED`\n- `limit` (optional): Max results (default: 50, max: 100)\n- `offset` (optional): Pagination offset\n- `sync` (optional): Set to `false` to skip live status sync (default: true)\n\n**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.\n\n**Example:**\n```bash\ncurl -H \"Authorization: Bearer $LUCKYLOBSTER_API_KEY\" \\\n  \"https://luckylobster.io/api/agent/v1/orders?status=OPEN\"\n```\n\n**Response includes sync info:**\n```json\n{\n  \"success\": true,\n  \"data\": [...],\n  \"sync\": { \"enabled\": true, \"updated\": 2 }\n}\n```\n\n### Get Order Status\n\nGet details for a specific order, including live status from Polymarket.\n\n```http\nGET /orders/{orderId}\n```\n\n**Example:**\n```bash\ncurl -H \"Authorization: Bearer $LUCKYLOBSTER_API_KEY\" \\\n  \"https://luckylobster.io/api/agent/v1/orders/ord_abc123\"\n```\n\n**Response:**\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"order\": {\n      \"id\": \"ord_abc123\",\n      \"polyOrderId\": \"0x...\",\n      \"tokenId\": \"123456...\",\n      \"side\": \"BUY\",\n      \"type\": \"LIMIT\",\n      \"price\": \"0.65\",\n      \"size\": \"50\",\n      \"filledSize\": \"25\",\n      \"status\": \"PARTIALLY_FILLED\",\n      \"marketQuestion\": \"Bitcoin Up or Down?\",\n      \"outcome\": \"Up\",\n      \"submittedAt\": \"2025-01-15T12:00:00Z\"\n    },\n    \"liveStatus\": {\n      \"polymarketStatus\": \"LIVE\",\n      \"originalSize\": 50,\n      \"sizeMatched\": 25,\n      \"price\": 0.65\n    }\n  }\n}\n```\n\n### Cancel Order\n\nCancel an open order. Only orders with status `PENDING`, `OPEN`, or `PARTIALLY_FILLED` can be cancelled.\n\n```http\nDELETE /orders/{orderId}\n```\n\n**Example:**\n```bash\ncurl -X DELETE -H \"Authorization: Bearer $LUCKYLOBSTER_API_KEY\" \\\n  \"https://luckylobster.io/api/agent/v1/orders/ord_abc123\"\n```\n\n**Response:**\n```json\n{\n  \"success\": true,\n  \"message\": \"Order cancelled successfully\",\n  \"data\": {\n    \"order\": {\n      \"id\": \"ord_abc123\",\n      \"polyOrderId\": \"0x...\",\n      \"status\": \"CANCELLED\",\n      \"previousStatus\": \"OPEN\",\n      \"filledSize\": \"25\",\n      \"cancelledAt\": \"2025-01-15T12:05:00Z\"\n    }\n  }\n}\n```\n\n**Error Responses:**\n- `400`: Order cannot be cancelled (already filled, cancelled, or failed)\n- `403`: Order was not placed by your agent\n- `404`: Order not found\n\n**Notes:**\n- You can only cancel orders that your agent placed\n- If an order is partially filled, cancelling stops further fills but keeps the filled portion\n- The `previousStatus` field shows what status the order had before cancellation\n\n### Close Position (One-Shot)\n\nClose an entire position with a single API call. The server handles determining the correct side, fetching current price, and placing the market order.\n\n```http\nPOST /positions/{positionId}/close\n```\n\n**URL Parameters:**\n- `positionId`: Position ID from `GET /positions`\n\n**Optional Body:**\n```json\n{\n  \"type\": \"MARKET\",   // Order type: \"MARKET\" (default), \"FOK\", or \"LIMIT\"\n  \"slippage\": 0.02,   // Max slippage for LIMIT orders (default: 2%)\n  \"dryRun\": true      // Preview without executing\n}\n```\n\n**Example - Close a position:**\n```bash\ncurl -X POST -H \"Authorization: Bearer $LUCKYLOBSTER_API_KEY\" \\\n  \"https://luckylobster.io/api/agent/v1/positions/pos_abc123/close\"\n```\n\n**Example - Preview first (dry run):**\n```bash\ncurl -X POST -H \"Authorization: Bearer $LUCKYLOBSTER_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"dryRun\": true}' \\\n  \"https://luckylobster.io/api/agent/v1/positions/pos_abc123/close\"\n```\n\n**Response:**\n```json\n{\n  \"success\": true,\n  \"message\": \"Position closed successfully\",\n  \"data\": {\n    \"order\": {\n      \"id\": \"ord_xyz789\",\n      \"polyOrderId\": \"0x...\",\n      \"status\": \"FILLED\",\n      \"side\": \"SELL\",\n      \"type\": \"MARKET\",\n      \"price\": 0.65,\n      \"size\": 100,\n      \"filledSize\": 100,\n      \"avgFillPrice\": 0.65,\n      \"transactionHash\": \"0x...\"\n    },\n    \"position\": {\n      \"id\": \"pos_abc123\",\n      \"remainingSize\": 0,\n      \"isClosed\": true\n    },\n    \"execution\": {\n      \"proceeds\": 65.00,\n      \"pnl\": 10.00,\n      \"pnlPercent\": 18.18\n    },\n    \"market\": {\n      \"slug\": \"bitcoin-up-or-down-on-february-3\",\n      \"question\": \"Bitcoin Up or Down on February 3?\",\n      \"outcome\": \"Up\"\n    }\n  }\n}\n```\n\n**Dry Run Response:**\n```json\n{\n  \"success\": true,\n  \"dryRun\": true,\n  \"message\": \"Position close preview - no order placed\",\n  \"data\": {\n    \"position\": {\n      \"id\": \"pos_abc123\",\n      \"tokenId\": \"123456...\",\n      \"size\": 100,\n      \"avgEntryPrice\": 0.55\n    },\n    \"closeOrder\": {\n      \"side\": \"SELL\",\n      \"type\": \"MARKET\",\n      \"price\": 0.65,\n      \"size\": 100\n    },\n    \"estimates\": {\n      \"currentPrice\": 0.65,\n      \"bidPrice\": 0.65,\n      \"proceeds\": 65.00,\n      \"pnl\": 10.00,\n      \"pnlPercent\": 18.18\n    }\n  }\n}\n```\n\n**Error Responses:**\n- `400`: Position is already closed (size=0) or already settled\n- `403`: Position belongs to another user\n- `404`: Position not found\n- `503`: Unable to fetch market price (market may be closed/illiquid)\n\n**Notes:**\n- Uses the current bid price for immediate execution\n- For LIMIT orders, applies slippage tolerance (default 2%) below bid\n- Position is partially closed if order only partially fills\n- Check `position.isClosed` to verify complete exit\n\n### Get Balance\n\nGet raw wallet balance (live from chain).\n\n```http\nGET /balance\n```\n\n**Response:**\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"usdc\": 93.16,\n    \"matic\": 0.5,\n    \"address\": \"0x1234...\",\n    \"walletType\": \"proxy\"\n  }\n}\n```\n\n**Fields:**\n- `usdc`: Raw USDC in wallet\n- `matic`: For gas (rarely needed)\n- `address`: Your trading wallet on Polygon\n\n### Approve Tokens (Fix \"not enough allowance\" errors)\n\nIf 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.\n\n```http\nPOST /wallet/approve\n```\n\n**Request Body:**\n```json\n{\n  \"token\": \"CTF\"  // or \"USDC\", \"NEG_RISK\", \"all\"\n}\n```\n\n**Token Types:**\n- `USDC`: Required for buying (usually already approved)\n- `CTF`: **Required for selling/closing positions**\n- `NEG_RISK`: Required for multi-outcome markets\n- `all`: Approve all tokens at once\n\n**Example - Fix selling errors:**\n```bash\ncurl -X POST -H \"Authorization: Bearer $LUCKYLOBSTER_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"token\": \"CTF\"}' \\\n  \"https://luckylobster.io/api/agent/v1/wallet/approve\"\n```\n\n**Response:**\n```json\n{\n  \"success\": true,\n  \"message\": \"CTF approved successfully\",\n  \"data\": {\n    \"approvals\": { \"CTF\": \"0x...\" },\n    \"successful\": [\"CTF\"],\n    \"failed\": []\n  }\n}\n```\n\n**When to use:**\n- Error: \"not enough balance / allowance\" when selling\n- Error: \"not enough balance / allowance\" when closing a position\n- First time selling after wallet setup\n\n### Get Budget\n\nGet how much you can spend. **Use this before placing orders.**\n\nBudget = min(wallet balance, fixed limit, % of wallet)\n\n```http\nGET /budget\n```\n\n**Response:**\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"usdc\": 46.58,\n    \"limitedBy\": \"percent\",\n    \"wallet\": 93.16,\n    \"config\": {\n      \"fixedLimit\": null,\n      \"budgetPercent\": 50,\n      \"maxPositionValue\": null,\n      \"used\": 0\n    }\n  }\n}\n```\n\n**Fields:**\n- `usdc`: **What you can spend** (accounts for all limits)\n- `limitedBy`: Why you're capped (`\"wallet\"`, `\"fixed_limit\"`, `\"percent\"`, `\"position_limit\"`)\n- `wallet`: Raw wallet balance\n- `config`: Your budget settings\n\n### Get Positions\n\nGet 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.\n\n```http\nGET /positions\n```\n\n**Parameters:**\n- `status` (optional): Filter by status - `\"open\"` (default), `\"settled\"`, `\"redeemable\"`, or `\"all\"`\n- `token_id` (optional): Filter by specific token ID\n- `condition_id` (optional): Filter by condition ID (market)\n- `source` (optional): Force data source - `\"clob\"` to bypass Data API and fetch directly from CLOB trades\n\n**Example - Get Open Positions:**\n```bash\ncurl -H \"Authorization: Bearer $LUCKYLOBSTER_API_KEY\" \\\n  \"https://luckylobster.io/api/agent/v1/positions\"\n```\n\n**Example - Get Redeemable Positions:**\n```bash\ncurl -H \"Authorization: Bearer $LUCKYLOBSTER_API_KEY\" \\\n  \"https://luckylobster.io/api/agent/v1/positions?status=redeemable\"\n```\n\n**Example - Force CLOB Source (for freshest data):**\n```bash\ncurl -H \"Authorization: Bearer $LUCKYLOBSTER_API_KEY\" \\\n  \"https://luckylobster.io/api/agent/v1/positions?source=clob\"\n```\n\n**Response:**\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"positions\": [\n      {\n        \"id\": \"0xabc123_0\",\n        \"tokenId\": \"12345...\",\n        \"conditionId\": \"0xabc123...\",\n        \"market\": {\n          \"slug\": \"bitcoin-up-or-down-on-february-3\",\n          \"question\": \"Bitcoin Up or Down on February 3?\",\n          \"outcome\": \"Up\",\n          \"endDate\": \"2026-02-03T17:00:00Z\",\n          \"eventSlug\": \"btc-updown\"\n        },\n        \"size\": 100.0,\n        \"avgEntryPrice\": 0.55,\n        \"currentPrice\": 0.62,\n        \"currentValue\": 62.00,\n        \"pnl\": {\n          \"unrealized\": 7.00,\n          \"unrealizedPercent\": 12.73,\n          \"realized\": 0.00,\n          \"realizedPercent\": 0.00\n        },\n        \"status\": {\n          \"isOpen\": true,\n          \"isSettled\": false,\n          \"isRedeemable\": false,\n          \"isMergeable\": false,\n          \"isNegRisk\": false\n        },\n        \"oppositeOutcome\": \"Down\",\n        \"oppositeAsset\": \"67890...\",\n        \"updatedAt\": \"2026-02-03T14:45:00.000Z\"\n      }\n    ],\n    \"summary\": {\n      \"totalPositions\": 1,\n      \"totalUnrealizedPnl\": 7.00,\n      \"totalRealizedPnl\": 0.00,\n      \"totalValue\": 62.00\n    },\n    \"filters\": {\n      \"status\": \"open\",\n      \"tokenId\": null,\n      \"conditionId\": null\n    },\n    \"wallet\": {\n      \"address\": \"0x539b2de928064898...\",\n      \"type\": \"proxy\"\n    },\n    \"source\": \"data-api\"\n  }\n}\n```\n\n**Key Fields:**\n- `size`: Number of outcome tokens held\n- `avgEntryPrice`: Average price paid per token (0.00 to 1.00)\n- `currentPrice`: Live price from Polymarket\n- `currentValue`: Current value in USDC\n- `pnl.unrealized`: Unrealized profit/loss\n- `pnl.unrealizedPercent`: Unrealized P&L as percentage\n- `status.isRedeemable`: `true` if market resolved and position can be redeemed\n- `status.isNegRisk`: `true` for multi-outcome markets (require special redemption)\n- `wallet.type`: `\"proxy\"` (Polymarket smart wallet) or `\"eoa\"` (direct wallet)\n- `source`: `\"data-api\"` or `\"clob-trades\"` - shows which data source was used\n\n**Data Source Behavior:**\n1. **Default**: Fetches from Polymarket Data API (most reliable, includes all historical positions)\n2. **Fallback**: If Data API returns empty, automatically falls back to CLOB trades\n3. **Forced CLOB**: Use `?source=clob` for freshest data immediately after placing an order (Data API can have ~30s delay)\n\n**When to use `source=clob`:**\n- Right after placing an order (Data API has indexing delay)\n- When Data API returns fewer positions than expected\n- For debugging position discrepancies\n\n---\n\n## Settlement & Redemption\n\nWhen 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.\n\n### List Redeemable Positions\n\nCheck what positions are ready for redemption.\n\n```http\nGET /settlements/redeem\n```\n\n**Response:**\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"positions\": [\n      {\n        \"conditionId\": \"0xbc13af0a940bb9a...\",\n        \"title\": \"Bitcoin Up or Down - February 4, 1:45PM-2:00PM ET\",\n        \"outcome\": \"Down\",\n        \"size\": 5.0,\n        \"estimatedValue\": \"$5.00\",\n        \"negRisk\": false\n      }\n    ],\n    \"count\": 3,\n    \"totalValue\": \"$42.50\",\n    \"wallet\": \"0x539b2de928064898...\"\n  },\n  \"message\": \"Found 3 redeemable positions (~$42.50). POST to redeem.\"\n}\n```\n\n### Redeem Positions\n\nRedeem winning positions in a single batched transaction. You can redeem all positions or target specific ones.\n\n```http\nPOST /settlements/redeem\n```\n\n**Optional Parameters:**\n```json\n{\n  \"conditionId\": \"0x...\",           // Redeem ONLY this specific position\n  \"conditionIds\": [\"0x...\", \"...\"], // Redeem ONLY these specific positions\n  \"limit\": 50,       // Max positions to redeem (default: 10, max: 50)\n  \"minValue\": 1.00,  // Skip positions below this value (default: $0.10)\n  \"dryRun\": true     // Preview what would be redeemed without executing\n}\n```\n\n**Example - Redeem a specific position:**\n```bash\ncurl -X POST -H \"X-API-Key: $LUCKYLOBSTER_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"conditionId\": \"0xbc13af0a940bb9a...\"}' \\\n  \"https://luckylobster.io/api/agent/v1/settlements/redeem\"\n```\n\n**Example - Redeem all:**\n```bash\ncurl -X POST -H \"X-API-Key: $LUCKYLOBSTER_API_KEY\" \\\n  \"https://luckylobster.io/api/agent/v1/settlements/redeem\"\n```\n\n**Example - Dry run first:**\n```bash\ncurl -X POST -H \"X-API-Key: $LUCKYLOBSTER_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"dryRun\": true}' \\\n  \"https://luckylobster.io/api/agent/v1/settlements/redeem\"\n```\n\n**Example - Redeem up to 50, skip dust:**\n```bash\ncurl -X POST -H \"X-API-Key: $LUCKYLOBSTER_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"limit\": 50, \"minValue\": 1.00}' \\\n  \"https://luckylobster.io/api/agent/v1/settlements/redeem\"\n```\n\n**Response:**\n```json\n{\n  \"success\": true,\n  \"message\": \"Redeemed 3 positions (~$42.50)\",\n  \"data\": {\n    \"processed\": 3,\n    \"redeemed\": [\n      {\n        \"conditionId\": \"0xbc13af0a...\",\n        \"title\": \"Bitcoin Up or Down - February 4, 1:45PM-2:00PM ET\",\n        \"outcome\": \"Down\",\n        \"size\": 5.0,\n        \"txHash\": \"0x82d8d7e4d63185...\"\n      }\n    ],\n    \"failed\": [],\n    \"remaining\": 0,\n    \"totalValueRedeemed\": \"$42.50\"\n  }\n}\n```\n\n**Error Responses:**\n- `404`: Wallet not found\n- `403`: Missing \"redeem\" permission\n- `501`: Polymarket Builder API not configured\n\n**Notes:**\n- Redemption is gasless (executed via Polymarket relayer)\n- All positions are batched into a single on-chain transaction for efficiency\n- Only positions marked as \"redeemable\" by Polymarket are included\n- Both standard and NegRisk markets are handled automatically\n\n---\n\n## Heartbeat (Status Check)\n\nThe heartbeat endpoint provides a single-call summary of your portfolio, pending actions, and account status. Call it periodically to stay informed.\n\n### Check Heartbeat\n\n```http\nGET /heartbeat?skill_version=10\n```\n\nInclude `skill_version` so the server can indicate if a newer version is available.\n\nReturns aggregated data: open positions, redeemable positions, filled orders since last check, budget status, and items that may need attention.\n\n**Response:**\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"status\": \"ACTION_NEEDED\",\n    \"timestamp\": \"2026-02-06T15:30:00Z\",\n    \"actions\": [\n      {\n        \"type\": \"REDEEM\",\n        \"priority\": \"high\",\n        \"summary\": \"2 positions ready to redeem (~$42.50)\",\n        \"details\": { \"positions\": [...], \"action\": \"POST /settlements/redeem\" }\n      },\n      {\n        \"type\": \"ORDER_FILLED\",\n        \"priority\": \"medium\",\n        \"summary\": \"3 order(s) filled since last check\",\n        \"details\": { \"fills\": [...], \"totalPnl\": 12.50 }\n      }\n    ],\n    \"portfolio\": {\n      \"openPositions\": 5,\n      \"totalValue\": 250.00,\n      \"unrealizedPnl\": 12.50,\n      \"redeemableCount\": 2,\n      \"redeemableValue\": 42.50\n    },\n    \"orderActivity\": {\n      \"openOrders\": 1,\n      \"filledSinceLastHeartbeat\": 3,\n      \"recentFills\": [...]\n    },\n    \"budget\": {\n      \"available\": 46.58,\n      \"limitedBy\": \"percent\",\n      \"walletBalance\": 93.16\n    },\n    \"heartbeat\": {\n      \"next_check_at\": \"2026-02-06T16:00:00Z\",\n      \"interval_ms\": 1800000,\n      \"active_hours\": { \"start\": \"09:00\", \"end\": \"22:00\", \"timezone\": \"America/New_York\" },\n      \"heartbeat_count\": 42,\n      \"latest_skill_version\": 10\n    },\n    \"realtime\": {\n      \"subscribedMarkets\": 3,\n      \"clobConnected\": true,\n      \"sportsConnected\": false,\n      \"cryptoConnected\": true\n    }\n  }\n}\n```\n\n**Status Values:**\n- `ACTION_NEEDED`: Items may need attention. Check the `actions` array.\n- `OK`: Nothing needs attention.\n- `SLEEPING`: Outside configured active hours.\n\n**Action Types:**\n- `REDEEM` (high): Settled positions ready for redemption. Call `POST /settlements/redeem`.\n- `ORDER_FILLED` (medium): Orders filled since last heartbeat. Includes P&L details.\n- `BUDGET_LOW` (medium): Budget running low.\n- `POSITION_EXPIRING` (low): Open positions in markets closing within 30 minutes.\n- `SEEK_TRADES` (low): Budget is available. Trading opportunities may exist — use `GET /markets/search` or `GET /markets/crypto` to browse.\n\n**Heartbeat Scheduling:**\n\nThe 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.\n\n---\n\n## Autonomous Strategies\n\nCreate 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.\n\n### Strategy Types\n\n**PRICE_ALERT** - Buy or sell when price hits a target (stop-loss, take-profit, limit buy)\n**RECURRING_BUY** - Dollar-cost average into a market at fixed intervals\n**BUY_LOW_SELL_HIGH** - Buy below a floor, sell above a ceiling, repeat\n\n### Create Strategy\n\n```\nPOST ${baseUrl}/api/agent/v1/strategies\nAuthorization: Bearer {api_key}\n\n// PRICE_ALERT example: Sell if price drops below 0.35\n{\n  \"name\": \"BTC Stop-Loss\",\n  \"type\": \"PRICE_ALERT\",\n  \"config\": {\n    \"marketQuery\": \"bitcoin\",\n    \"outcome\": \"Yes\",\n    \"side\": \"SELL\",\n    \"triggerCondition\": \"PRICE_LTE\",\n    \"triggerPrice\": 0.35,\n    \"size\": 100,\n    \"orderType\": \"MARKET\"\n  },\n  \"maxBudget\": 50\n}\n\n// RECURRING_BUY example: Buy $10 of Bitcoin every hour\n{\n  \"name\": \"BTC Recurring Hourly\",\n  \"type\": \"RECURRING_BUY\",\n  \"config\": {\n    \"marketQuery\": \"bitcoin\",\n    \"outcome\": \"Yes\",\n    \"amountPerInterval\": 10,\n    \"interval\": \"1h\",\n    \"maxTotalAmount\": 200,\n    \"priceLimit\": 0.70\n  },\n  \"maxBudget\": 200\n}\n\n// BUY_LOW_SELL_HIGH example: Buy below 0.40, sell above 0.60\n{\n  \"name\": \"BTC Range Trader\",\n  \"type\": \"BUY_LOW_SELL_HIGH\",\n  \"config\": {\n    \"marketQuery\": \"bitcoin\",\n    \"outcome\": \"Yes\",\n    \"buyBelow\": 0.40,\n    \"sellAbove\": 0.60,\n    \"sizePerTrade\": 50,\n    \"maxOpenSize\": 200\n  },\n  \"maxBudget\": 500\n}\n\n// COPY_TRADE example: Mirror a wallet's trades with $10 per copy\n{\n  \"name\": \"Copy Whale\",\n  \"type\": \"COPY_TRADE\",\n  \"config\": {\n    \"targetAddress\": \"0x1234567890abcdef1234567890abcdef12345678\",\n    \"sizingMode\": \"fixed\",\n    \"fixedAmount\": 10,\n    \"copySells\": true,\n    \"maxPositionSize\": 500\n  },\n  \"maxBudget\": 500\n}\n\n// COPY_TRADE proportional example: Copy 50% of target's trade size\n{\n  \"name\": \"Mirror Trader\",\n  \"type\": \"COPY_TRADE\",\n  \"config\": {\n    \"targetAddress\": \"0xabcdefabcdefabcdefabcdefabcdefabcdefabcd\",\n    \"sizingMode\": \"proportional\",\n    \"proportionPct\": 50,\n    \"copySells\": true\n  },\n  \"maxBudget\": 1000\n}\n```\n\n### COPY_TRADE Config Fields\n\n| Field | Required | Description |\n|-------|----------|-------------|\n| `targetAddress` | Yes | Wallet address to copy (0x + 40 hex chars) |\n| `sizingMode` | Yes | `\"fixed\"` (fixed USDC per trade) or `\"proportional\"` (% of target's size) |\n| `fixedAmount` | When fixed | USDC to spend per copy trade |\n| `proportionPct` | When proportional | 1-100, percentage of target's trade size |\n| `copySells` | Yes | `true` to also copy sell trades, `false` for buys only |\n| `maxPositionSize` | No | Max shares to hold per token |\n| `tokenFilter` | No | Array of token IDs — only copy trades for these tokens |\n\nCopy trading monitors the Polygon blockchain in real-time (~2 second detection). It cannot copy your own wallet.\n\n### List Strategies\n\n```\nGET ${baseUrl}/api/agent/v1/strategies\nGET ${baseUrl}/api/agent/v1/strategies?status=ACTIVE&type=DCA\n```\n\n### Get Strategy Details\n\n```\nGET ${baseUrl}/api/agent/v1/strategies/{id}\n```\n\nReturns full strategy with last 20 execution records.\n\n### Update Strategy\n\n```\nPATCH ${baseUrl}/api/agent/v1/strategies/{id}\n{ \"config\": { ... }, \"maxBudget\": 300 }\n```\n\n### Pause / Resume / Cancel\n\n```\nPOST ${baseUrl}/api/agent/v1/strategies/{id}/pause\nPOST ${baseUrl}/api/agent/v1/strategies/{id}/resume\nDELETE ${baseUrl}/api/agent/v1/strategies/{id}\n```\n\n### Strategy Lifecycle\n\n1. **ACTIVE** - Server evaluates every ~10 seconds\n2. **PAUSED** - Paused by user (from dashboard) or agent. Not evaluated until resumed.\n3. **ERROR** - Auto-paused after 3 consecutive failures. Use `POST /strategies/{id}/resume` to retry.\n4. **COMPLETED** - Budget exhausted or one-shot trigger fired\n5. **CANCELLED** - Cancelled by user (from dashboard) or agent. Cannot be resumed.\n6. **EXPIRED** - Past 24-hour default TTL (or custom `expiresAt`). Cannot be resumed.\n\n### Crypto Market Auto-Discovery\n\nFor 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.\n\n### COPY_TRADE Real-Time Monitoring\n\nCopy 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.\n\n### Heartbeat Integration\n\nThe heartbeat response includes a `strategies` section and these action types:\n- **STRATEGY_EXECUTED** (medium) — Trades placed by your strategies\n- **STRATEGY_ERROR** (high) — Strategies auto-paused after consecutive errors\n- **STRATEGY_COMPLETED** (low) — Strategies that finished (budget exhausted or trigger fired)\n- **STRATEGY_PAUSED** (high) — Strategy paused by the user from the dashboard. `POST /strategies/{id}/resume` to restart.\n- **STRATEGY_CANCELLED** (high) — Strategy cancelled by the user from the dashboard. Create a new strategy if needed.\n\n### Best Practices\n\n1. **Set maxBudget** on every strategy to limit exposure\n2. **Use PRICE_ALERT** for stop-loss/take-profit on existing positions\n3. **Use RECURRING_BUY with marketQuery** for crypto markets (handles market expiry)\n4. **Review heartbeat** periodically to see strategy execution results\n5. **Max 10 active strategies** per agent\n\n---\n\n## Error Handling\n\n```json\n{\n  \"success\": false,\n  \"error\": \"Error Type\",\n  \"message\": \"Human-readable message\"\n}\n```\n\n**Status Codes:**\n- `401`: Invalid API key\n- `403`: Insufficient permissions or budget exceeded\n- `404`: Resource not found\n- `429`: Rate limit exceeded\n\n## Permissions\n\n- `read`: View markets, orders, positions, balance\n- `trade`: Place orders\n- `cancel`: Cancel orders\n- `redeem`: Redeem settled positions\n","topics":["Trading"],"tags":{"latest":"0.10.0"},"stats":{"comments":0,"downloads":2022,"installsAllTime":76,"installsCurrent":0,"stars":1,"versions":5},"createdAt":1770386919454,"updatedAt":1779076682594},"latestVersion":{"version":"0.10.0","createdAt":1771652046174,"changelog":"Skill v10 — synced from production deploy","license":null},"metadata":{"setup":[{"key":"LUCKYLOBSTER_API_KEY","required":true}],"os":null,"systems":null},"owner":{"handle":"rachelbastian","userId":"s1762x8f2ycca6p9w41bw0jba9884s5a","displayName":"LuckyLobster","image":"https://avatars.githubusercontent.com/u/107372767?v=4"},"moderation":{"isSuspicious":false,"isMalwareBlocked":false,"verdict":"clean","reasonCodes":["review.llm_review"],"summary":"Review: review.llm_review","engineVersion":"v2.4.24","updatedAt":1779954405063}}