# How to Integrate Polymarket Trading with Outcome Tokens in AI-Trader

> Learn to integrate Polymarket trading with outcome tokens in AI-Trader. Discover how AI-Trader uses Polymarket's API for pricing and execution of simulated trades.

- Repository: [✨Data Intelligence Lab@HKU✨/AI-Trader](https://github.com/HKUDS/AI-Trader)
- Tags: how-to-guide
- Published: 2026-05-09

---

**AI-Trader treats Polymarket as a spot-like paper-trading market, using Polymarket's public Gamma API for discovery and CLOB for pricing, while handling simulated execution and bookkeeping internally.**

The AI-Trader framework from HKUDS supports decentralized prediction market trading by mapping Polymarket outcome tokens to a unified trading interface. Unlike traditional spot markets, Polymarket requires resolution of human-readable outcomes (e.g., *Yes*/*No*) to specific ERC-20 token IDs before trading. This guide explains the complete integration workflow using the actual source implementation.

## Discovering Markets via the Gamma API

Polymarket market discovery happens entirely outside AI-Trader. According to the **[Polymarket skill]** documentation, agents must query Polymarket's public Gamma API directly to obtain market definitions.

The endpoint `https://gamma-api.polymarket.com/markets` returns market metadata including the question, slug, outcome labels, and the critical `clobTokenIds` array that links each outcome to its on-chain token.

```python
import requests

def resolve_market(slug):
    """Resolve a Polymarket market via Gamma and return token_id/outcome."""
    resp = requests.get(
        "https://gamma-api.polymarket.com/markets",
        params={"slug": slug, "limit": "1"},
    )
    data = resp.json()[0]
    outcomes = data["outcomes"]
    token_ids = data["clobTokenIds"]
    # Assume we want the first outcome (e.g., 'Yes')

    return token_ids[0], outcomes[0]

```

## Resolving References to Outcome Token IDs

Once you have market data, you must map the human-readable outcome to its concrete `token_id`. The **[price_fetcher]** module contains two key utilities for this resolution.

**Extracting tokens from market data:** The helper `_polymarket_extract_tokens` (lines 302‑312 in [`price_fetcher.py`](https://github.com/HKUDS/AI-Trader/blob/main/price_fetcher.py)) parses the `outcomes` and `clobTokenIds` arrays from the Gamma response, returning a structured list of `{token_id, outcome}` pairs.

**Resolving trade references:** When a trade request supplies a market reference—whether as a `slug`, `conditionId`, or raw `token_id`—the function `_polymarket_resolve_reference` (lines 315‑369 in [`price_fetcher.py`](https://github.com/HKUDS/AI-Trader/blob/main/price_fetcher.py)) deterministically resolves the exact `token_id` and outcome. This function caches results for fast repeated look-ups, preventing redundant API calls during high-frequency trading scenarios.

## Fetching Live Price Data from the CLOB

After resolving the token ID, AI-Trader fetches the current market price from Polymarket's Central Limit Order Book (CLOB). The function `_get_polymarket_mid_price` (lines 720‑746 in [`price_fetcher.py`](https://github.com/HKUDS/AI-Trader/blob/main/price_fetcher.py)) queries `https://clob.polymarket.com/book` to retrieve the best bid and ask.

It computes the mid-price between bid/ask spread, validates the value against outliers, and falls back to Gamma-provided outcome prices when the CLOB endpoint is unavailable or illiquid. This ensures the paper-trading simulation always has a valid reference price for PnL calculations.

## Submitting Trades to the Signals Endpoint

With the `token_id` and current price established, you submit trades to AI-Trader's `/signals` endpoint. The **[routes_signals]** handler enforces Polymarket-specific constraints at lines 75‑94 and 119‑130, validating that:

- The `action` is either `"buy"` or `"sell"` (short/cover actions are explicitly rejected at lines 110‑113 in **[services]**)
- The `token_id` is present for all Polymarket trades (enforced at lines 190‑195 in **[services]**)

### Required Payload Structure

```json
{
  "market": "polymarket",
  "symbol": "will-btc-be-above-120k-on-june-30",
  "action": "buy",
  "outcome": "Yes",
  "token_id": "123456789",
  "price": 0,
  "quantity": 20,
  "executed_at": "now"
}

```

**Key fields:**
- **`market`**: Must be the literal string `"polymarket"`
- **`symbol`**: The market slug or `conditionId`
- **`outcome`**: Human-readable label (e.g., *Yes*, *No*)
- **`token_id`**: The concrete CLOB token ID (optional only if the outcome uniquely identifies a single token, though **[services]** enforces its presence at lines 190‑195)
- **`action`**: Only `"buy"` or `"sell"` permitted
- **`price`**: Set to `0`—AI-Trader fetches the live price automatically via `_get_polymarket_mid_price`
- **`quantity`**: Amount of outcome tokens to trade
- **`executed_at`**: Use `"now"` for immediate execution

### Complete Python Client Example

```python
import requests

BASE_URL = "https://ai-trader.example.com"  # replace with your AI-Trader host

SIGNALS_ENDPOINT = f"{BASE_URL}/signals"

def submit_polymarket_trade(slug, action, quantity):
    token_id, outcome = resolve_market(slug)
    payload = {
        "market": "polymarket",
        "symbol": slug,
        "action": action,  # "buy" or "sell"

        "outcome": outcome,
        "token_id": token_id,
        "price": 0,  # ignored – server fetches live price

        "quantity": quantity,
        "executed_at": "now",
    }
    r = requests.post(SIGNALS_ENDPOINT, json=payload)
    r.raise_for_status()
    return r.json()

# Example usage

print(submit_polymarket_trade("will-btc-be-above-120k-on-june-30", "buy", 20))

```

### Direct cURL Alternative

```bash

# 1) Resolve the market

curl "https://gamma-api.polymarket.com/markets?slug=will-btc-be-above-120k-on-june-30"

# 2) Submit the trade to AI-Trader

curl -X POST https://ai-trader.example.com/signals \
  -H "Content-Type: application/json" \
  -d '{
        "market": "polymarket",
        "action": "buy",
        "symbol": "will-btc-be-above-120k-on-june-30",
        "outcome": "Yes",
        "token_id": "123456789",
        "price": 0,
        "quantity": 20,
        "executed_at": "now"
      }'

```

## Position Management and Auto-Settlement

When the **[routes_signals]** handler validates and accepts a payload (lines 218‑238), it forwards the request to the generic trade handler in **[services]** (lines 190‑213). This service layer persists positions indexed by both `token_id` and `outcome`, ensuring accurate tracking of distinct prediction market positions.

**Settlement handling:** Resolved Polymarket markets are automatically settled by a background task in [`tasks.py`](https://github.com/HKUDS/AI-Trader/blob/main/tasks.py). This task polls the Gamma API for the `resolved` flag and settlement price, then updates open positions accordingly. This eliminates manual intervention for expired markets while maintaining accurate PnL attribution.

## Summary

- **Market Discovery**: Query `gamma-api.polymarket.com` directly; AI-Trader does not proxy discovery
- **Token Resolution**: Use `_polymarket_resolve_reference` in [`price_fetcher.py`](https://github.com/HKUDS/AI-Trader/blob/main/price_fetcher.py) (lines 315‑369) to map slugs/outcomes to `token_id`s
- **Price Fetching**: `_get_polymarket_mid_price` (lines 720‑746) computes mid-prices from the CLOB or falls back to Gamma data
- **Trade Constraints**: Submit only `buy`/`sell` actions to `/signals` with required fields `market`, `symbol`, `outcome`, and `token_id`
- **Validation**: [`routes_signals.py`](https://github.com/HKUDS/AI-Trader/blob/main/routes_signals.py) (lines 75‑94) and [`services.py`](https://github.com/HKUDS/AI-Trader/blob/main/services.py) (lines 190‑213) enforce Polymarket-specific rules including `token_id` presence and short-sale prohibition
- **Settlement**: Background tasks in [`tasks.py`](https://github.com/HKUDS/AI-Trader/blob/main/tasks.py) handle automatic resolution of expired markets

## Frequently Asked Questions

### What is the difference between the Gamma API and the CLOB endpoint?

The **Gamma API** (`gamma-api.polymarket.com`) provides static market metadata including questions, slugs, and token IDs. The **CLOB** (`clob.polymarket.com/book`) provides dynamic order-book data including live bid/ask prices. AI-Trader uses Gamma for discovery and token resolution, while using CLOB for real-time price fetching.

### Why are short and cover actions blocked for Polymarket?

According to [`services.py`](https://github.com/HKUDS/AI-Trader/blob/main/services.py) lines 110‑113, AI-Trader rejects `short` and `cover` actions because Polymarket outcome tokens are spot assets representing discrete event probabilities. Unlike perpetual contracts or margin markets, prediction market tokens cannot be shorted in the traditional sense—you can only sell tokens you already own (position reduction) or buy new ones.

### Is the `token_id` field always required in the trade payload?

Yes. While the resolution logic in [`price_fetcher.py`](https://github.com/HKUDS/AI-Trader/blob/main/price_fetcher.py) can sometimes infer a token ID from the outcome name alone, the validation logic in [`services.py`](https://github.com/HKUDS/AI-Trader/blob/main/services.py) lines 190‑195 explicitly requires `token_id` to be present in the payload for all Polymarket trades. This prevents ambiguity in markets with multiple outcomes or similar naming.

### How does AI-Trader handle market resolution and settlement?

A background task defined in [`tasks.py`](https://github.com/HKUDS/AI-Trader/blob/main/tasks.py) periodically scans open Polymarket positions. When the Gamma API indicates a market has `resolved: true` with a final settlement price, the task automatically updates the position's exit price and realized PnL. This emulates the automatic redemption of outcome tokens at resolution without requiring manual trade closure.