Kalshi is the first and only CFTC-regulated prediction market exchange in the United States. Unlike crypto-native platforms, Kalshi operates under federal oversight with fiat-based settlement, traditional API patterns, and legal compliance for U.S. institutions.

For developers, this means familiar patterns — REST over HTTPS, WebSocket for streaming, and even FIX 4.4 for institutional trading — but with some unique quirks around authentication and market structure. This guide covers everything you need to go from zero to a production trading bot on Kalshi.

Last verified: February 2026. Check the Kalshi Changelog for the latest updates.


Why Kalshi for Agents

Kalshi stands apart from Polymarket in several ways that matter for autonomous agents:

  • Regulated: CFTC Designated Contract Market — legal for U.S. entities and institutions
  • Fiat settlement: USD deposits and withdrawals via traditional banking (no crypto wallets needed)
  • Demo environment: Full-featured sandbox for testing without real money
  • Zero trading fees: As of 2026, Kalshi charges 0% fees on trades
  • FIX protocol support: Institutional-grade connectivity for low-latency strategies
  • Familiar auth patterns: RSA-PSS signed requests, not blockchain wallet signatures

The tradeoff: Kalshi has less total liquidity than Polymarket, fewer concurrent markets, and more restricted market categories (due to CFTC oversight). But for agents operating within U.S. regulatory frameworks, or for strategies that need the demo environment for safe testing, Kalshi is often the better starting point.


Architecture Overview

Kalshi’s API is simpler than Polymarket’s — there’s essentially one API with different access methods.

InterfaceURLPurpose
REST APIhttps://trading-api.kalshi.com/trade-api/v2Market data, order management, account operations
Demo RESThttps://demo-api.kalshi.co/trade-api/v2Full sandbox environment (same endpoints)
WebSocketwss://trading-api.kalshi.com/trade-api/ws/v2Real-time market and order updates
Demo WebSocketwss://demo-api.kalshi.co/trade-api/ws/v2Sandbox WebSocket
FIX 4.4Contact Kalshi for connection detailsInstitutional low-latency trading

All market data, trading, and account endpoints live under the same base URL. This is a major simplification compared to Polymarket’s multi-service architecture.


How Kalshi Markets Work

Understanding Kalshi’s market structure is essential before you start coding.

Event Contracts

Every Kalshi market is a binary contract that pays out $1.00 if the event occurs, or $0.00 if it doesn’t. You buy contracts at prices between $0.01 and $0.99 (expressed in cents internally — more on this below).

Example: A contract asking “Will Bitcoin be above $100,000 on March 31?” might be trading at $0.65 (65 cents). If Bitcoin is above $100K on that date, you receive $1.00 per contract. If not, you receive $0.00. Your profit on a YES bet is $0.35 per contract; your risk is $0.65.

Ticker Format

Kalshi tickers encode market information directly:

KXNFLGAME-25OCT12CLEPIT
│ │       │  │     │
│ │       │  │     └── Teams (CLE vs PIT)
│ │       │  └──────── Date (October 12)
│ │       └─────────── Year (2025)
│ └─────────────────── Series (NFL Game)
└───────────────────── KX prefix (Kalshi Exchange)

INXCHI-25JAN31-T69.5
│     │        │
│     │        └── Threshold value
│     └─────────── Expiry date
└───────────────── Series ticker

Prices in Cents

Critical detail: Kalshi prices are expressed in cents (integers), not decimals. A price of 65 means $0.65. When placing orders, you submit 6500 for a $0.65 limit price (or 65 depending on the endpoint — check the documentation carefully). This is different from Polymarket where prices are decimal (0.65).


Getting Started: Demo Environment

The biggest advantage Kalshi has for developers is a fully functional demo environment. Use it.

Demo REST: https://demo-api.kalshi.co/trade-api/v2
Demo WebSocket: wss://demo-api.kalshi.co/trade-api/ws/v2

The demo environment has:

  • Fake money with no risk
  • All the same endpoints as production
  • Real-ish market data to test against
  • Separate API keys from production

Always build and test in demo first. Switch to production only after your bot behaves correctly.


Authentication: RSA-PSS Signing

Kalshi uses RSA-PSS (Probabilistic Signature Scheme) for API authentication. This is more complex than a simple API key header, but provides stronger security.

Step 1: Generate API Keys

  1. Log into your Kalshi account (or demo account)
  2. Go to Settings → API
  3. Generate a new API key pair
  4. Download the private key (PEM file) — store this securely
  5. Note the API Key ID — this is your public identifier

Step 2: Understand the Signing Process

Every authenticated request requires three custom headers:

KALSHI-ACCESS-KEY: <your-api-key-id>
KALSHI-ACCESS-SIGNATURE: <rsa-pss-signature>
KALSHI-ACCESS-TIMESTAMP: <unix-timestamp-in-milliseconds>

The signature is computed over the concatenation of: timestamp + method + path

Step 3: Implement Request Signing (Python)

import time
import base64
import requests
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.asymmetric import padding

class KalshiClient:
    def __init__(self, key_id: str, private_key_path: str, base_url: str = None):
        self.key_id = key_id
        self.base_url = base_url or "https://trading-api.kalshi.com/trade-api/v2"

        with open(private_key_path, "rb") as f:
            self.private_key = serialization.load_pem_private_key(
                f.read(), password=None
            )

    def _sign(self, timestamp_ms: str, method: str, path: str) -> str:
        """Sign the request using RSA-PSS"""
        message = f"{timestamp_ms}{method}{path}".encode("utf-8")
        signature = self.private_key.sign(
            message,
            padding.PSS(
                mgf=padding.MGF1(hashes.SHA256()),
                salt_length=padding.PSS.MAX_LENGTH
            ),
            hashes.SHA256()
        )
        return base64.b64encode(signature).decode("utf-8")

    def _headers(self, method: str, path: str) -> dict:
        """Generate authenticated headers for a request"""
        timestamp = str(int(time.time() * 1000))
        signature = self._sign(timestamp, method, path)
        return {
            "KALSHI-ACCESS-KEY": self.key_id,
            "KALSHI-ACCESS-SIGNATURE": signature,
            "KALSHI-ACCESS-TIMESTAMP": timestamp,
            "Content-Type": "application/json",
            "Accept": "application/json"
        }

    def get(self, path: str, params: dict = None):
        url = f"{self.base_url}{path}"
        headers = self._headers("GET", path)
        return requests.get(url, headers=headers, params=params)

    def post(self, path: str, data: dict = None):
        url = f"{self.base_url}{path}"
        headers = self._headers("POST", path)
        return requests.post(url, headers=headers, json=data)

    def delete(self, path: str, data: dict = None):
        url = f"{self.base_url}{path}"
        headers = self._headers("DELETE", path)
        return requests.delete(url, headers=headers, json=data)

Using the Demo Environment

# For demo/testing:
client = KalshiClient(
    key_id="your-demo-api-key-id",
    private_key_path="path/to/demo-private-key.pem",
    base_url="https://demo-api.kalshi.co/trade-api/v2"
)

# For production:
client = KalshiClient(
    key_id="your-prod-api-key-id",
    private_key_path="path/to/prod-private-key.pem",
    base_url="https://trading-api.kalshi.com/trade-api/v2"
)

Using the Official Python SDK

Kalshi provides an official Python SDK that handles authentication for you:

import kalshi_python

config = kalshi_python.Configuration()
config.host = "https://demo-api.kalshi.co/trade-api/v2"  # Demo

kalshi_api = kalshi_python.ApiInstance(
    email="[email protected]",
    password="your-password",
    configuration=config
)

# Check exchange status
status = kalshi_api.get_exchange_status()
print(status)

Note: The SDK also supports API key authentication. Check the kalshi-python PyPI page for the latest version.


REST API Reference

Market Data (Public)

GET /markets — List All Markets

response = client.get("/markets", params={
    "limit": 20,
    "status": "open"
})

for market in response.json()["markets"]:
    print(f"{market['ticker']}: {market['title']}")
    print(f"  Yes price: {market.get('yes_ask', 'N/A')}")
    print(f"  Volume: {market.get('volume', 0)}")

Key response fields:

  • ticker — Unique market identifier (e.g., KXNFLGAME-25OCT12CLEPIT)
  • title — Human-readable description
  • statusopen, closed, settled
  • yes_bid / yes_ask — Best bid and ask for YES contracts
  • no_bid / no_ask — Best bid and ask for NO contracts
  • volume — Number of contracts traded
  • open_interest — Number of outstanding contracts
  • expiration_time — When the market expires

GET /markets/{ticker} — Get Single Market

response = client.get("/markets/KXNFLGAME-25OCT12CLEPIT")
market = response.json()["market"]

GET /markets/{ticker}/orderbook — Get Order Book

response = client.get("/markets/KXNFLGAME-25OCT12CLEPIT/orderbook")
book = response.json()["orderbook"]

print("YES bids:", book.get("yes", []))
print("NO bids:", book.get("no", []))

The order book returns bid and ask levels with quantities at each price point.

GET /events — List Events

Events group related markets together (e.g., all NFL Week 10 games).

response = client.get("/events", params={"status": "open"})
events = response.json()["events"]

GET /series — List Series

Series are higher-level groupings (e.g., “NFL Games”, “Fed Rate Decisions”).

response = client.get("/series")

Trading (Authenticated)

POST /orders — Place an Order

import uuid

order = {
    "ticker": "KXNFLGAME-25OCT12CLEPIT",
    "side": "yes",           # "yes" or "no"
    "type": "limit",         # "limit" or "market"
    "action": "buy",         # "buy" or "sell"
    "count": 10,             # Number of contracts
    "yes_price": 65,         # Price in cents (65 = $0.65)
    "client_order_id": str(uuid.uuid4())  # Your tracking ID
}

response = client.post("/orders", data=order)
print(response.json())

Order parameters:

  • ticker — The market ticker
  • sideyes or no
  • actionbuy or sell
  • typelimit or market
  • count — Number of contracts
  • yes_price — Limit price in cents (for limit orders)
  • client_order_id — Optional idempotency key for tracking
  • expiration_ts — Optional expiration time for the order

GET /orders — List Your Orders

response = client.get("/orders", params={
    "status": "resting"  # resting, canceled, executed
})

DELETE /orders/{order_id} — Cancel an Order

response = client.delete(f"/orders/{order_id}")

POST /orders/{order_id}/decrease — Decrease Order Size

Reduce the number of contracts on an existing order without canceling and replacing.

response = client.post(f"/orders/{order_id}/decrease", data={
    "reduce_by": 5
})

Account & Positions

GET /portfolio/positions — Get Your Positions

response = client.get("/portfolio/positions")
positions = response.json()["positions"]

for pos in positions:
    print(f"{pos['ticker']}: {pos['position']} contracts")
    print(f"  Market exposure: ${pos.get('market_exposure', 0) / 100:.2f}")

GET /portfolio/balance — Check Your Balance

response = client.get("/portfolio/balance")
balance = response.json()
print(f"Available: ${balance['balance'] / 100:.2f}")

GET /portfolio/settlements — Settlement History

response = client.get("/portfolio/settlements")

Historical Data

GET /markets/history — Historical Market Data

Kalshi provides historical cutoff timestamps and historical data endpoints for backtesting.

response = client.get("/markets/history", params={
    "ticker": "KXNFLGAME-25OCT12CLEPIT"
})

WebSocket API

For real-time data, Kalshi’s WebSocket API streams order book updates, trade executions, and market status changes.

Connection with Authentication

import asyncio
import base64
import json
import time
import websockets
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.asymmetric import padding

KEY_ID = "your-api-key-id"
PRIVATE_KEY_PATH = "path/to/private-key.pem"
WS_URL = "wss://demo-api.kalshi.co/trade-api/ws/v2"  # Demo

def load_private_key():
    with open(PRIVATE_KEY_PATH, "rb") as f:
        return serialization.load_pem_private_key(f.read(), password=None)

def sign_ws_message(private_key, timestamp_ms: str) -> str:
    message = f"{timestamp_ms}GET/trade-api/ws/v2".encode("utf-8")
    signature = private_key.sign(
        message,
        padding.PSS(
            mgf=padding.MGF1(hashes.SHA256()),
            salt_length=padding.PSS.MAX_LENGTH
        ),
        hashes.SHA256()
    )
    return base64.b64encode(signature).decode("utf-8")

async def stream_kalshi():
    private_key = load_private_key()
    timestamp = str(int(time.time() * 1000))
    signature = sign_ws_message(private_key, timestamp)

    headers = {
        "KALSHI-ACCESS-KEY": KEY_ID,
        "KALSHI-ACCESS-SIGNATURE": signature,
        "KALSHI-ACCESS-TIMESTAMP": timestamp
    }

    async with websockets.connect(WS_URL, additional_headers=headers) as ws:
        print("Connected to Kalshi WebSocket")

        # Subscribe to ticker updates
        await ws.send(json.dumps({
            "id": 1,
            "cmd": "subscribe",
            "params": {
                "channels": ["ticker"]
            }
        }))

        # Subscribe to orderbook for a specific market
        await ws.send(json.dumps({
            "id": 2,
            "cmd": "subscribe",
            "params": {
                "channels": ["orderbook_delta"],
                "market_tickers": ["KXNFLGAME-25OCT12CLEPIT"]
            }
        }))

        async for message in ws:
            data = json.loads(message)
            print(f"Update: {data}")

asyncio.run(stream_kalshi())

Available Channels

Private channels (require authentication):

  • orderbook_delta — Real-time order book changes for specific markets
  • fill — Your trade executions
  • market_positions — Your position updates
  • order_group_updates — Order status changes

Public channels (no auth required):

  • ticker — Market-wide ticker updates for all markets
  • trade — Public trade feed
  • market_lifecycle_v2 — Market open/close/settlement events
  • multivariate — Multi-outcome market updates

Keepalive

The Python websockets library handles keepalive automatically. Other WebSocket libraries may require manual ping/pong implementation.


FIX 4.4 Protocol

For institutional-grade connectivity, Kalshi supports the FIX (Financial Information eXchange) 4.4 protocol — the same protocol used by major stock and futures exchanges.

FIX is relevant if you:

  • Have existing FIX trading infrastructure
  • Need the lowest possible latency
  • Are building for an institutional trading desk

Contact Kalshi directly for FIX connection details and certification requirements.


Rate Limits

Kalshi implements tiered rate limits. Key guidelines:

  • REST API latency is typically 50–200ms
  • Rate limits make true high-frequency trading impractical via REST
  • WebSocket feeds are better suited for latency-sensitive strategies
  • Kalshi may offer elevated limits for market makers and institutional accounts

If you’re hitting rate limits:

  1. Use WebSocket for real-time data instead of polling
  2. Reduce polling frequency for non-critical data
  3. Cache market metadata (tickers, descriptions) — it rarely changes
  4. Contact Kalshi support about elevated limits for your use case

Putting It Together: A Complete Trading Bot

Here’s a minimal but functional bot that monitors a market and places orders based on a simple threshold strategy:

import time
import uuid
import logging

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("kalshi-bot")

class SimpleKalshiBot:
    def __init__(self, client: KalshiClient, ticker: str):
        self.client = client
        self.ticker = ticker
        self.position = 0
        self.max_position = 50  # Max contracts to hold

    def get_market_price(self) -> dict:
        """Fetch current market prices"""
        response = self.client.get(f"/markets/{self.ticker}")
        market = response.json()["market"]
        return {
            "yes_bid": market.get("yes_bid"),
            "yes_ask": market.get("yes_ask"),
            "no_bid": market.get("no_bid"),
            "no_ask": market.get("no_ask"),
            "volume": market.get("volume", 0)
        }

    def check_position(self):
        """Get current position in this market"""
        response = self.client.get("/portfolio/positions", params={
            "ticker": self.ticker
        })
        positions = response.json().get("positions", [])
        for pos in positions:
            if pos["ticker"] == self.ticker:
                self.position = pos.get("position", 0)
                return
        self.position = 0

    def place_order(self, side: str, action: str, count: int, price: int):
        """Place a limit order"""
        order = {
            "ticker": self.ticker,
            "side": side,
            "type": "limit",
            "action": action,
            "count": count,
            "yes_price": price,
            "client_order_id": str(uuid.uuid4())
        }
        response = self.client.post("/orders", data=order)

        if response.status_code == 200:
            logger.info(f"Order placed: {side} {action} {count}x @ {price}c")
        else:
            logger.error(f"Order failed: {response.text}")

        return response

    def run(self, buy_threshold: int, sell_threshold: int, interval: int = 10):
        """
        Simple threshold strategy:
        - Buy YES if price drops below buy_threshold
        - Sell YES if price rises above sell_threshold
        """
        logger.info(f"Starting bot for {self.ticker}")
        logger.info(f"Buy below: {buy_threshold}c | Sell above: {sell_threshold}c")

        while True:
            try:
                prices = self.get_market_price()
                self.check_position()

                yes_ask = prices["yes_ask"]
                yes_bid = prices["yes_bid"]

                logger.info(
                    f"Price: bid={yes_bid}c ask={yes_ask}c | "
                    f"Position: {self.position} contracts"
                )

                # Buy signal
                if (yes_ask and yes_ask <= buy_threshold
                        and self.position < self.max_position):
                    contracts = min(5, self.max_position - self.position)
                    self.place_order("yes", "buy", contracts, yes_ask)

                # Sell signal
                if (yes_bid and yes_bid >= sell_threshold
                        and self.position > 0):
                    contracts = min(5, self.position)
                    self.place_order("yes", "sell", contracts, yes_bid)

            except Exception as e:
                logger.error(f"Error: {e}")

            time.sleep(interval)


# Usage:
client = KalshiClient(
    key_id="your-key-id",
    private_key_path="path/to/key.pem",
    base_url="https://demo-api.kalshi.co/trade-api/v2"  # START WITH DEMO
)

bot = SimpleKalshiBot(client, ticker="KXNFLGAME-25OCT12CLEPIT")
bot.run(buy_threshold=40, sell_threshold=60, interval=10)

Common Patterns for Agent Builders

Pattern 1: Multi-Market Scanner

Scan all open markets for opportunities matching your criteria.

def scan_markets(client, min_volume=1000, max_yes_price=30):
    """Find underpriced YES contracts with decent volume"""
    response = client.get("/markets", params={
        "status": "open",
        "limit": 200
    })

    opportunities = []
    for market in response.json()["markets"]:
        vol = market.get("volume", 0)
        yes_ask = market.get("yes_ask")

        if vol >= min_volume and yes_ask and yes_ask <= max_yes_price:
            opportunities.append({
                "ticker": market["ticker"],
                "title": market["title"],
                "yes_ask": yes_ask,
                "volume": vol
            })

    return sorted(opportunities, key=lambda x: x["volume"], reverse=True)

Pattern 2: Cross-Platform Arbitrage (Kalshi ↔ Polymarket)

Compare prices on the same event across both platforms.

def find_cross_platform_arbs(kalshi_client, polymarket_markets):
    """
    Compare Kalshi and Polymarket prices for matching events.
    Requires a mapping of Kalshi tickers to Polymarket token IDs.
    """
    kalshi_response = kalshi_client.get("/markets", params={
        "status": "open", "limit": 200
    })

    for kalshi_market in kalshi_response.json()["markets"]:
        ticker = kalshi_market["ticker"]

        # Check if we have a Polymarket match
        if ticker in polymarket_markets:
            kalshi_yes = kalshi_market.get("yes_ask", 100) / 100
            poly_no = polymarket_markets[ticker]["no_price"]

            combined = kalshi_yes + poly_no
            if combined < 0.98:  # 2%+ arb
                print(f"ARB: {ticker}")
                print(f"  Kalshi YES: ${kalshi_yes:.2f}")
                print(f"  Poly NO: ${poly_no:.2f}")
                print(f"  Combined: ${combined:.2f}")
                print(f"  Edge: ${1.0 - combined:.4f}")

Pattern 3: News-Driven Trading

React to news events by monitoring external sources and executing on Kalshi.

import time

def news_driven_strategy(client, ticker, news_monitor):
    """
    When positive news hits, buy YES.
    When negative news hits, buy NO.
    """
    while True:
        signal = news_monitor.get_latest_signal(ticker)

        if signal and signal["confidence"] > 0.7:
            side = "yes" if signal["direction"] == "positive" else "no"
            market = client.get(f"/markets/{ticker}").json()["market"]

            # Get current ask price for our side
            price_key = f"{side}_ask"
            price = market.get(price_key)

            if price:
                client.post("/orders", data={
                    "ticker": ticker,
                    "side": side,
                    "type": "limit",
                    "action": "buy",
                    "count": 5,
                    "yes_price": price if side == "yes" else (100 - price),
                    "client_order_id": str(uuid.uuid4())
                })

        time.sleep(30)

Pattern 4: Portfolio Monitoring Dashboard

Pull all positions and compute aggregate P&L.

def portfolio_summary(client):
    """Get a complete portfolio summary"""
    balance = client.get("/portfolio/balance").json()
    positions = client.get("/portfolio/positions").json().get("positions", [])

    total_exposure = 0
    total_unrealized = 0

    print(f"Cash Balance: ${balance['balance'] / 100:.2f}")
    print(f"\nOpen Positions:")
    print("-" * 60)

    for pos in positions:
        exposure = pos.get("market_exposure", 0) / 100
        total_exposure += exposure

        print(f"  {pos['ticker']}")
        print(f"    Side: {pos.get('side', 'N/A')}")
        print(f"    Contracts: {pos.get('position', 0)}")
        print(f"    Exposure: ${exposure:.2f}")

    print("-" * 60)
    print(f"Total Exposure: ${total_exposure:.2f}")
    print(f"Total Portfolio: ${(balance['balance'] / 100) + total_exposure:.2f}")

Production Deployment Checklist

Before taking your bot from demo to production:

Security:

  • Private keys stored in environment variables or a secrets manager (never in code)
  • API key permissions scoped to only what’s needed
  • Separate keys for demo and production
  • No secrets committed to version control

Risk Management:

  • Maximum position size limits per market
  • Maximum total portfolio exposure limit
  • Kill switch to cancel all orders and halt trading
  • Daily loss limit with automatic shutdown
  • Slippage protection on market orders

Reliability:

  • Automatic reconnection for WebSocket disconnections (exponential backoff)
  • Graceful error handling for all API calls
  • Logging of every order placed and every error encountered
  • Health check / heartbeat monitoring

Operational:

  • Tested extensively in demo environment
  • Start with very small position sizes in production
  • Monitor manually for the first 24-48 hours
  • Alerts set up for unusual behavior (large losses, connection failures)
  • Rate limit awareness built into request logic

Kalshi vs. Polymarket: Choosing Your Platform

FactorKalshiPolymarket
RegulationCFTC-regulated (legal for U.S. institutions)Unregulated (crypto-native, geo-restricted)
SettlementUSD via traditional bankingUSDC on Polygon blockchain
AuthenticationRSA-PSS signed requestsEIP-712 wallet signatures
Demo EnvironmentYes — full sandboxNo demo available
Trading Fees0% (as of 2026)Variable (taker fees by market type, maker rebates)
LiquidityLower overallSignificantly higher
Market CategoriesRegulated subset (politics, economics, sports)Broader (crypto, culture, anything)
API ProtocolsREST, WebSocket, FIX 4.4REST, WebSocket
Best ForRegulated agents, institutional use, safe testingHigh-volume trading, crypto markets, maximum liquidity

For many agent builders, the optimal approach is to start on Kalshi’s demo environment to test your logic safely, then deploy to both platforms to maximize opportunity and diversification.

See our Polymarket API Guide for the complete Polymarket reference.


Troubleshooting

Authentication errors (401/403):

  • Verify your timestamp is in milliseconds (not seconds)
  • Check that you’re signing the correct string: timestamp + method + path
  • Ensure your private key file is the correct PEM format
  • Remember: demo and production use separate keys

“Order rejected” errors:

  • Check market status — it may be closed or settled
  • Verify your price is within valid range (1-99 cents)
  • Ensure you have sufficient balance
  • Check that you haven’t exceeded position limits

Rate limit errors (429):

  • Reduce polling frequency
  • Switch to WebSocket for real-time data
  • Cache market metadata
  • Implement exponential backoff on retries

WebSocket disconnections:

  • Implement automatic reconnection with exponential backoff
  • Re-subscribe to channels after reconnecting
  • The websockets Python library handles keepalive automatically — other libraries may need manual ping/pong

Demo vs Production discrepancies:

  • Some market data in demo may be synthetic or delayed
  • Demo order execution may differ slightly from production
  • Always re-verify behavior with small production orders before scaling

Official Resources

Community SDKs and Tools


Where This Fits in the Agent Betting Stack

This guide covers Layer 3 (Trading) of the Agent Betting Stack. Kalshi’s API is one execution venue for converting intelligence into positions — and for many U.S.-based agents, it’s the only fully legal one.

To build a complete autonomous agent, you also need:


This guide is maintained by AgentBets.ai. Found an error or API change we missed? Let us know on Twitter.

Not financial advice. Built for builders.