Build a prediction market odds bot for X
Kalshi and Polymarket, posted when they move
Both exchanges serve their markets through free, keyless APIs. Save the odds, compare on every run, and post the markets that moved. A 50-line script and no X developer account.
Card required, cancel any time.
The short answer
Every 15 minutes, call GET https://external-api.kalshi.com/trade-api/v2/events?status=open&with_nested_markets=true (no key), keep the events in your category, and compare each market's last_price_dollars with the price you saved last time. Post moves of 10 points or more on markets with real 24-hour volume to POST https://opentweet.io/api/v1/posts. For Polymarket, the same idea works on gamma-api.polymarket.com/events with outcomePrices.
Prediction markets had their biggest week yet. Kalshi reported $4.15 billion in notional volume on Election Day, November 3, 2026, and about $65 billion for October, with Polymarket US above $10 billion for the month (company figures, as reported by the trade press). On Google Trends, searches for "kalshi" in the last two weeks ran at almost twice their three-month average. Odds accounts already run on OpenTweet: in the last 30 days, 10 paying accounts posted market odds through it, from weekly NFL Super Bowl odds to macro accounts that quote the market next to the data.
Six formats an odds account posts
Pick one niche. Kalshi alone had thousands of open markets on November 6; an account that posts all of them is noise.
Big movers
Every 15 minA market that moved 10 points or more since the last check, with the volume behind it. The post people turn notifications on for.
Daily board
DailyThe five busiest markets in your niche and their odds, as a thread, at the same hour every day.
Event night
LiveElection night, a Fed decision, a title game: the odds every few minutes while it is live, then the result.
Weekly sports lines
WeeklyTitle odds after each round or week, like the paying account that posts NFL Super Bowl odds every week.
Kalshi vs Polymarket
DailyThe same question priced on both venues. When they disagree by a lot, it is a post.
Scorecard
After each eventWhat the market said the day before, and what happened. Honest scorekeeping builds trust.
Where the odds come from
We called the Kalshi and Polymarket endpoints without a key on November 6, 2026. Access and limits are from each provider's docs.
| Source | What it gives you | Access and limits | Note |
|---|---|---|---|
| Kalshi Trade API v2 | Events, markets, prices in dollars, 24h volume, open interest, trades, order books | No key for market data; Basic tier about 20 requests/s; 429 when over | US-regulated exchange; events carry a category (Economics, Sports, Elections...) |
| Polymarket Gamma API | Events and markets with outcomes, prices, one-day change, 24h volume | No key; rate limit numbers not published | outcomes and outcomePrices are JSON strings; parse them |
| Polymarket CLOB API | Order books and price history per token | No key for reads | For charts and "since last week" posts |
| Your own snapshots | The price at your last check | A JSON file or a table | The cleanest way to say "moved X points since" |
# Polymarket: today's busiest events, no key
curl -s "https://gamma-api.polymarket.com/events?active=true&closed=false&order=volume24hr&ascending=false&limit=5"
# Each market: outcomes '["Yes","No"]', outcomePrices '["0.085","0.915"]',
# oneDayPriceChange, lastTradePrice, volume24hrA Kalshi movers bot in Python
Reads open events in one category, compares every market with the price saved on the last run, and posts moves of 10 points or more on markets with at least 5,000 contracts traded in 24 hours. The first run only saves prices. Run it from cron every 15 minutes. We ran it against the live API on November 6, 2026 (with the post call swapped for a print).
import os, json, requests
from pathlib import Path
KALSHI = "https://external-api.kalshi.com/trade-api/v2"
OT = {"Authorization": f"Bearer {os.environ['OPENTWEET_API_KEY']}"}
CATEGORY = "Economics" # or Elections, Politics, Sports, Financials...
MOVE = 0.10 # post when a market moves 10 points or more
MIN_VOLUME = 5_000 # contracts traded in 24h; skips thin markets
LAST = Path("last_prices.json")
last = json.loads(LAST.read_text()) if LAST.exists() else {}
events, cursor = [], None
while True:
r = requests.get(f"{KALSHI}/events", timeout=30, params={
"status": "open", "with_nested_markets": "true", "limit": 200, **({"cursor": cursor} if cursor else {})})
r.raise_for_status()
page = r.json()
events += [e for e in page["events"] if e.get("category") == CATEGORY]
cursor = page.get("cursor")
if not cursor or len(events) > 300:
break
now = {}
for ev in events:
for m in ev["markets"]:
price = float(m["last_price_dollars"])
now[m["ticker"]] = price
before = last.get(m["ticker"])
if before is None or float(m["volume_24h_fp"]) < MIN_VOLUME:
continue
if abs(price - before) >= MOVE:
arrow = "up" if price > before else "down"
text = (f"{m['title']}\n\n"
f"Kalshi: {price:.0%} yes, {arrow} from {before:.0%} since the last check. "
f"{float(m['volume_24h_fp']):,.0f} contracts traded in 24h.")
requests.post("https://opentweet.io/api/v1/posts", headers=OT,
json={"text": text, "publish_now": True}).raise_for_status()
LAST.write_text(json.dumps({**last, **now}))What a post looks like
Will there be a recession in 2027?
Kalshi: 26% yes, down from 46% since the last check. 45,431 contracts traded in 24h.For a daily board, sort markets by volume_24h_fp and post the top five as one thread with is_thread and thread_tweets; see post a thread from the API.
Let an AI agent say why it moved
A number moving is a fact; the reason is the post people share. Connect Claude, ChatGPT or Cursor to the OpenTweet MCP server and give it the mover plus the news you trust:
Keep the prices and volumes in code and let the model write only the words around them. More on running a voice-driven account in build an AI Twitter persona.
Which plan fits your bot
Flat monthly price, no per-post fee. A daily board thread counts as one post toward the daily limit.
| Setup | Typical volume | Plan |
|---|---|---|
| Daily board plus the big movers in one niche | Up to 20 posts a day | Pro, $19.99/mo |
| Event nights, or politics, economics and sports on 3 accounts | Up to 100 posts a day, 3 X accounts | Advanced, $29/mo |
| A network of niche odds accounts | Up to 300 posts a day, 10 X accounts | Agency, $49/mo |
Posts with a URL count toward link posts: Pro 1 a day, Advanced 10, Agency 20, plus link credits. See pricing.
Report odds, don't sell bets. "Kalshi has it at 26%" is information, like a poll. "Take the yes before it moves" is a tip. Prediction markets and betting are restricted in many states and countries, so a referral link or a call to bet is a different kind of post.
Disclose deals. If an exchange pays you, use X's Paid Partnership label and say so in the bio.
Label the bot. Turn on X's Automated label, name the person who runs it, and never auto-reply odds under other people's posts. More in X automation rules.
Thin markets move on one trade. A market with a few hundred contracts can jump 30 points on a single order. Keep a volume floor (the script uses 5,000 contracts in 24 hours), and say "last trade" rather than "the market thinks" when the spread between bid and ask is wide.
Frequently asked questions
How do I build a bot that posts prediction market odds to X?
Read open markets from Kalshi (GET https://external-api.kalshi.com/trade-api/v2/events?status=open&with_nested_markets=true) or Polymarket (GET https://gamma-api.polymarket.com/events?active=true&closed=false), save each market's price, and on the next run post the ones that moved more than your threshold to POST https://opentweet.io/api/v1/posts. A daily board of the biggest markets at a fixed time is the second format. OpenTweet posts through a normal X login, so you need no X developer account.
Does the Kalshi API need an API key for market data?
No. Kalshi's docs describe market data as available without authentication, and the markets and events endpoints declare no security requirement. We called them without a key on November 6, 2026. The recommended base URL is https://external-api.kalshi.com/trade-api/v2, and api.elections.kalshi.com still works. You need a key only to trade, and for the WebSocket feed.
What fields hold the price in the Kalshi API?
Prices are strings in dollars from 0 to 1: last_price_dollars (the last traded YES price), yes_bid_dollars, yes_ask_dollars, no_bid_dollars and no_ask_dollars. Volume is volume_24h_fp and volume_fp, and open_interest_fp is open interest. A last price of 0.67 reads as a 67% chance. The older yes_bid and last_price names are not in the current schema.
How do I read Polymarket odds from the API?
Gamma API (https://gamma-api.polymarket.com) needs no key for markets and events. Each market has outcomes and outcomePrices, both JSON-encoded strings, for example ["Yes", "No"] and ["0.085", "0.915"] sent as text; parse them and match by index (index 0 is Yes on binary markets). oneDayPriceChange, lastTradePrice and volume24hr are also on the market. Sort events with order=volume24hr&ascending=false for what is busiest today.
What are the Kalshi API rate limits?
Kalshi uses token buckets: the Basic tier gets 200 read tokens a second and most requests cost 10, so about 20 requests a second. Over the limit you get HTTP 429 with no Retry-After header, so back off exponentially. A bot that checks once every 15 minutes needs a handful of requests per run.
Can I post Kalshi or Polymarket referral links?
A referral link is promotion of a betting product, so check what is legal where your followers are, and use X's Paid Partnership label if you are paid for it. On OpenTweet any post with a URL is a link post: 1 a day on Pro, 10 on Advanced and 20 on Agency, plus link credits. Most odds accounts post the number and the market name and leave the link out.
Posting results instead of odds? See the election results bot and the sports stats bot. Company news? See the SEC filings bot.
Everything you can build on X with OpenTweet
Post to X from your code, a watcher, or an AI agent. Start anywhere in the cluster.
OpenTweet vs the X API
Post, schedule, and automate X without a developer account or the $200/mo minimum.
X DM outreach, human-approved
Find and qualify leads, AI-draft DMs, approve each one, and drip-send from your own account via API or MCP.
Post to X without an API
The clean, account-safe way to post to X from your code or an AI agent.
Twitter MCP Server
Give Claude, Cursor, and OpenClaw the ability to post to X. 44 tools included.
Developer docs
Quickstart, API keys, MCP setup, and the REST reference for posting to X from code or an agent.
Cross-posting reference
One call posts to X, Bluesky and LinkedIn. The platforms field, per-network results, and why a network gets skipped.
Social media API for AI agents
Three ways an agent can post to X, Bluesky and LinkedIn, and the trade-offs of each.
LinkedIn MCP server
Post and schedule to a LinkedIn profile from Claude or Cursor through the official LinkedIn API.
XMCP vs OpenTweet
X's official MCP server bills per API call and cannot schedule. Compare it with the flat-fee hosted MCP.
MCP for AI agents
Connect your AI client to X in under two minutes, no X developer account.
Developer API and keys
REST endpoints, one bearer key, and usage tracking. Build on OpenTweet.
OpenTweet for AI agents
The posting layer for autonomous agents and automations that live on X.
Build an AI Twitter persona
Give your AI agent its own X account. Setup, cadence, and the rules that keep it safe.
Best MCP servers for social media
The 2026 ranked list. How the hosted OpenTweet MCP compares with the official X MCP and others.
Best API to post to X
Seven options priced at real volumes, and why links decide the bill.
Cheapest way to post to X via code
Flat fee vs pay-per-use. Why the $0.20 per-link fee flips the math past ~145 link posts a month.
X API pricing 2026
Every pay-per-use X API endpoint price from docs.x.com in one searchable table.
Bluesky posting API
Post and schedule to Bluesky with one REST call and OAuth, and cross-post to X and LinkedIn in the same request.
Automate LinkedIn posts
Post to LinkedIn from an AI agent, n8n or a script through the official Posts API, with one REST or MCP call.
The odds move, your account posts it first
Connect X, create a key, and start the movers bot tonight.