Manifold Markets prediction market API guide. Use when: (1) Fetching/searching markets or market data, (2) Placing bets, limit orders, or multi-bets, (3) Selling shares or canceling orders, (4) Analyzing positions, portfolios, or profit, (5) Building trading bots, (6) WebSocket real-time updates, (7) Bulk data via Supabase, (8) Creating/editing/resolving markets, (9) Comments, reactions, follows, managrams, or DMs, (10) Querying transactions or bet history, (11) AMM math/simulation.
/plugin marketplace add Thomas-Lemoine/manifold-markets-skill/plugin install manifold-markets@manifold-markets-toolsThis skill inherits all available tools. When active, it can use any tool Claude has access to.
references/amm.mdreferences/betting.mdreferences/data-structures.mdreferences/endpoint-audit.mdreferences/markets.mdreferences/social.mdreferences/supabase.mdreferences/transactions.mdreferences/users.mdreferences/websocket.mdscripts/utils.py| Item | Value |
|---|---|
| Base URL | https://api.manifold.markets/v0 |
| Root URL | https://api.manifold.markets (some endpoints) |
| Auth Header | Authorization: Key {api_key} |
| Rate Limit | 500 req/min per IP |
| Timestamps | JavaScript milliseconds (NOT seconds) |
Get your API key at: https://manifold.markets/profile
import os
import requests
API_KEY = os.getenv("MANIFOLD_API_KEY")
BASE = "https://api.manifold.markets/v0"
headers = {"Authorization": f"Key {API_KEY}"}
r = requests.get(f"{BASE}/me", headers=headers)
If an authenticated request is needed, ask the user to export their API key first:
export MANIFOLD_API_KEY="your-key-here"
The user can get their key from https://manifold.markets/profile or their .env file.
Then use in curl commands:
curl -H "Authorization: Key $MANIFOLD_API_KEY" https://api.manifold.markets/v0/me
The export lasts for the terminal session (until the window is closed).
r = requests.get(f"{BASE}/market/{market_id}")
r = requests.get(f"{BASE}/slug/{market_slug}")
r = requests.get(f"{BASE}/search-markets", params={
"term": "AI",
"filter": "open", # all, open, closed, resolved, closing-this-month, closing-next-month
"sort": "liquidity", # See sort options below
"limit": 50, # Max 100
})
# Valid sort options (from schema.ts):
# score (default), newest, daily-score, freshness-score, 24-hour-vol,
# most-popular, liquidity, subsidy, last-updated, close-date,
# start-time, resolve-date, random, bounty-amount, prob-descending, prob-ascending
#
# NOTE: There is NO "volume" sort. Use Supabase for all-time volume ranking.
# Market order
r = requests.post(f"{BASE}/bet", headers=headers, json={
"contractId": market_id,
"amount": 100,
"outcome": "YES",
})
# Limit order (IOC - expires quickly)
r = requests.post(f"{BASE}/bet", headers=headers, json={
"contractId": market_id,
"amount": 100,
"outcome": "YES",
"limitProb": 0.60,
"expiresMillisAfter": 10,
})
# Multiple choice (requires answerId)
r = requests.post(f"{BASE}/bet", headers=headers, json={
"contractId": market_id,
"answerId": answer_id,
"amount": 100,
"outcome": "YES",
})
r = requests.post(f"{BASE}/market/{market_id}/sell", headers=headers, json={
"outcome": "YES",
"shares": 50, # Optional, sells all if omitted
"answerId": answer_id, # Required for MC
})
r = requests.get(f"{BASE}/user/{username}")
r = requests.get(f"{BASE}/market/{market_id}/positions", params={"userId": user_id})
| Type | Mechanism | Description |
|---|---|---|
BINARY | cpmm-1 | YES/NO, variable p parameter |
MULTIPLE_CHOICE | cpmm-multi-1 | Multiple answers, always p=0.5 |
PSEUDO_NUMERIC | cpmm-1 | Numeric range mapped to 0-1 |
POLL | none | Non-tradeable voting |
BOUNTIED_QUESTION | none | Bounty for best answer |
shouldAnswersSumToOne determines behavior:
false → Independent answers (each is its own YES/NO)true → Mutually exclusive (probabilities sum to 1)A market can be bet on only if:
trading_allowed = (
not market.get("isResolved") and
(not market.get("closeTime") or market["closeTime"] > time.time() * 1000) and
market.get("mechanism") != "none" and
(answer is None or not answer.get("resolution")) # For MC
)
# General formula
prob = pool_no**(1-p) / (pool_yes**p + pool_no**(1-p))
# Multi-choice (always p=0.5)
prob = pool_no / (pool_yes + pool_no)
| Issue | Solution |
|---|---|
| Timestamps are milliseconds | close_time_sec = market["closeTime"] / 1000 |
| Some booleans are strings | {"dryRun": "true"} not {"dryRun": True} |
MC markets need answerId | Always include for multi-choice bets |
| Search excludes fields | Fetch full market if you need answers, description |
| Answer pools are nested | answer["pool"]["YES"], answer["pool"]["NO"] |
| Root vs /v0/ paths | Some endpoints at root (no /v0/), see reference files |
| No all-time volume sort | REST API has no sort=volume. Use Supabase (see recipes below) |
profitByTopic is a list | Not a dict. Iterate with for item in profitByTopic |
winRate is a percentage | Value of 62.5 means 62.5%, not 0.625 |
maxDrawdown is a percentage | Value of 25 means 25%, not 0.25 |
| Supabase timestamps need ISO | Use datetime.now(timezone.utc).isoformat(), not milliseconds |
The REST API cannot sort by all-time volume. Use Supabase instead:
from supabase import create_client
SUPABASE_URL = "https://pxidrgkatumlvfqaxcll.supabase.co"
SUPABASE_ANON_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InB4aWRyZ2thdHVtbHZmcWF4Y2xsIiwicm9sZSI6ImFub24iLCJpYXQiOjE2Njg5OTUzOTgsImV4cCI6MTk4NDU3MTM5OH0.d_yYtASLzAoIIGdXUBIgRAGLBnNow7JG2SoaNMQ8ySg"
sb = create_client(SUPABASE_URL, SUPABASE_ANON_KEY)
# Top 10 by all-time volume (volume is in data->volume JSON path)
result = (
sb.table("contracts")
.select("id, question, slug, visibility, data")
.eq("visibility", "public")
.order("data->volume", desc=True)
.limit(10)
.execute()
)
for m in result.data:
vol = m["data"].get("volume", 0)
creator = m["data"].get("creatorUsername", "")
print(f"{int(vol):,} M - {m['question']}")
print(f" https://manifold.markets/{creator}/{m['slug']}")
Use the REST API with sort=24-hour-vol:
r = requests.get(f"{BASE}/search-markets", params={
"sort": "24-hour-vol",
"filter": "open",
"limit": 10,
})
{"message": "Contract not found"}
{"message": "Insufficient balance"}
{"message": "Market is closed"}
Errors return HTTP 4xx/5xx with a message field.
Organized by domain:
| File | Contents |
|---|---|
| markets.md | Create, fetch, search, edit, resolve markets, groups/topics |
| betting.md | Place bets, limit orders, multi-bet, sell, cancel |
| users.md | Profiles, positions, portfolios, activity, loans, performance stats |
| social.md | Comments, reactions, follows, manalinks, DMs, transactions |
| data-structures.md | Response schemas, endpoint comparison (which endpoint returns what), sort options |
| amm.md | AMM math formulas, bet sizing, arbitrage |
| websocket.md | Real-time updates via WebSocket |
| supabase.md | Bulk data access, sorting by volume and other JSON fields |
| endpoint-audit.md | Complete endpoint inventory with documentation status |
from concurrent.futures import ThreadPoolExecutor
def fetch_markets_parallel(market_ids, max_workers=10):
def fetch_one(mid):
return requests.get(f"{BASE}/market/{mid}").json()
with ThreadPoolExecutor(max_workers=max_workers) as ex:
return list(ex.map(fetch_one, market_ids))
# Batch probability fetch (100x faster, up to 100 markets)
r = requests.get(f"{BASE}/market-probs",
params=[("ids[]", mid) for mid in market_ids[:100]])
# Batch market fetch (root path) - note bracket notation
r = requests.get("https://api.manifold.markets/markets-by-ids",
params=[("ids[]", mid) for mid in market_ids])
For long-running operations (scanning users, bulk fetches, etc.), cache to ~/.cache/manifold-markets/ to avoid polluting the user's repo. Use checkpointing with processed_ids for resumable operations.
The following endpoints exist but require special privileges or are for internal use:
admin-*, super-ban-user, recover-user, anonymize-user, toggle-system-trading-statusget-mod-reports, update-mod-report, dismiss-user-report*-gidx endpoints for KYC/sweepstakes compliancerecord-contract-view, record-comment-view, record-contract-interactionDon't use these unless you have appropriate permissions.
This skill should be used when the user asks to "create a hookify rule", "write a hook rule", "configure hookify", "add a hookify rule", or needs guidance on hookify rule syntax and patterns.
Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.