Cross-platform prediction market data infrastructure. Bidweave ingests markets from Polymarket and Kalshi, normalizes them into canonical events via embedding similarity and LLM validation, and exposes a unified API for querying events, prices, and linked news.
https://swarm-1gnx.onrender.com
Events are cross-platform normalized groupings of markets about the same topic. Each event has a consensus price, total volume, and linked markets from both Polymarket and Kalshi.
Markets are raw prediction markets from individual platforms, with bid/ask/spread data and price snapshots.
# Get top events by volume curl /api/events?limit=5&status=active # Search by topic curl -X POST /api/markets/search \ -H "Content-Type: application/json" \ -d '{"text": "bitcoin price"}'
Most read endpoints are public and require no authentication. The /api/query/* endpoints require an API key.
Pass your key via the X-Api-Key header. Keys are rate-limited to 60 requests per minute.
| X-Api-Key header | Your API key (required for /api/query/* endpoints only) |
curl /api/query/search \
-H "X-Api-Key: your_key_here" \
-H "Content-Type: application/json" \
-d '{"text": "federal reserve"}'
List canonical events with optional filters. Returns paginated results sorted by total volume (default).
| limit integer | Max results (default: 200, max: 500) |
| offset integer | Pagination offset (default: 0) |
| status string | "active" or "resolved" (default: all) |
| category string | Filter by category (e.g. "Politics", "Sports") |
| min_volume number | Minimum total volume filter |
| sort_by string | "volume", "title", "odds", "markets", "updated" (default: "volume") |
| sort_dir string | "asc" or "desc" (default: "desc") |
curl /api/events?limit=2&status=active&sort_by=volume
{
"events": [
{
"id": 42,
"title": "Will Bitcoin exceed $100k in 2025?",
"category": "Crypto",
"category_group": "Crypto",
"consensus_price": 0.72,
"market_count": 3,
"total_volume": 1250000,
"updated_at": "2025-03-15T12:00:00Z"
}
],
"total": 156,
"limit": 2,
"offset": 0
}
Get a single canonical event with all linked markets and their latest prices.
| id integer Required | Event ID |
curl /api/events/42
{
"id": 42,
"title": "Will Bitcoin exceed $100k in 2025?",
"category": "Crypto",
"category_group": "Crypto",
"consensus_price": 0.72,
"market_count": 3,
"total_volume": 1250000,
"markets": [
{
"platform": "polymarket",
"title": "Bitcoin above $100k?",
"mid_price": 0.73,
"last_price": 0.73,
"yes_bid": 0.72,
"yes_ask": 0.74,
"spread": 0.02,
"volume": 850000,
"volume_24h": 45000,
"open_interest": null,
"floor_strike": null,
"strike_type": null,
"category_group": "Crypto",
"event_id": 42
}
]
}
Get price history for all markets in an event. Returns time-series snapshots for each linked market.
| id integer Required | Event ID |
curl /api/events/42/price-history
{
"event_id": 42,
"markets": [
{
"market_id": 101,
"platform": "polymarket",
"title": "Bitcoin above $100k?",
"snapshots": [
{
"captured_at": "2025-03-15T12:00:00Z",
"mid_price": 0.73,
"volume": 850000
}
]
}
]
}
Get news articles linked to an event, grouped by story cluster with novelty scores. Also returns a flat articles array for backwards compatibility.
| id integer Required | Event ID |
| limit integer | Max articles (default: 20) |
| offset integer | Pagination offset (default: 0) |
| cluster_id integer | Story cluster ID |
| title string | Cluster representative title |
| summary string | Human-readable summary: single title or top 3 article titles joined by " | " |
| novelty_score number | 0-1 novelty score (higher = more novel) |
| similarity number | 256-dim cosine similarity to event |
| similarity_3072 number | 3072-dim cosine similarity to event |
| first_seen string | Earliest article timestamp in cluster |
| source_count integer | Number of source articles in cluster |
| articles array | Source articles: { id, title, url, source, published_at } |
curl /api/events/42/articles
{
"event_id": 42,
"stories": [
{
"cluster_id": 1205,
"title": "Bitcoin Rally Continues...",
"summary": "Bitcoin Rally Continues...",
"novelty_score": 0.85,
"similarity": 0.82,
"similarity_3072": 0.91,
"first_seen": "2025-03-14T08:30:00Z",
"source_count": 3,
"articles": [
{
"id": 501,
"title": "Bitcoin Rally Continues...",
"url": "https://example.com/article",
"source": "Reuters",
"published_at": "2025-03-14"
}
]
}
],
"articles": [
{
"id": 501,
"title": "Bitcoin Rally Continues...",
"url": "https://example.com/article",
"source": "Reuters",
"similarity": 0.82,
"published_at": "2025-03-14"
}
]
}
Chronological story flow for an event, ordered by first_seen. Shows how the narrative around an event has evolved over time.
| id integer Required | Event ID |
| limit integer | Max entries (default: 50) |
| offset integer | Pagination offset (default: 0) |
curl /api/events/42/timeline
{
"event_id": 42,
"event_title": "Will Bitcoin exceed $100k in 2025?",
"timeline": [
{
"cluster_id": 1205,
"title": "Bitcoin Rally Continues...",
"novelty_score": 0.85,
"similarity": 0.82,
"similarity_3072": 0.91,
"source_count": 3,
"first_seen": "2025-03-14T08:30:00Z",
"last_seen": "2025-03-14T14:00:00Z"
}
]
}
Recent high-novelty stories linked to any event. Use this to discover breaking news and novel developments across all tracked events.
| min_novelty number | Minimum novelty score (default: 0.0) |
| hours integer | Lookback window in hours (default: 48) |
| limit integer | Max results (default: 50) |
| offset integer | Pagination offset (default: 0) |
curl /api/stories/recent?min_novelty=0.7&hours=24&limit=10
{
"stories": [
{
"cluster_id": 1205,
"title": "Bitcoin Rally Continues...",
"summary": "Bitcoin Rally Continues...",
"source_count": 3,
"first_seen": "2025-03-14T08:30:00Z",
"last_seen": "2025-03-14T14:00:00Z",
"event_id": 42,
"event_title": "Will Bitcoin exceed $100k?",
"similarity": 0.82,
"similarity_3072": 0.91,
"novelty_score": 0.85
}
]
}
Get cross-platform matched market pairs for an event. Shows which Polymarket and Kalshi markets were matched by embedding similarity and LLM validation.
| id integer Required | Event ID |
curl /api/events/42/matches
{
"event_id": 42,
"pairs": [
{
"market_a": {
"id": 101,
"platform": "polymarket",
"title": "Bitcoin above $100k by June?",
"mid_price": 0.73,
"volume": 850000
},
"market_b": {
"id": 205,
"platform": "kalshi",
"title": "Will Bitcoin exceed $100,000?",
"mid_price": 0.71,
"volume": 620000
},
"sim_256": 0.89,
"sim_3072": 0.94,
"llm_verdict": "MATCH",
"validated_at": "2025-03-14T12:00:00Z"
}
],
"count": 1
}
List raw markets from Polymarket and Kalshi with optional filters.
| limit integer | Max results (default: 200, max: 500) |
| offset integer | Pagination offset (default: 0) |
| platform string | "polymarket" or "kalshi" |
| status string | "active" or "resolved" |
| min_volume number | Minimum volume filter |
| max_volume number | Maximum volume filter |
| min_spread number | Minimum spread filter |
| price_min number | Minimum mid_price |
| price_max number | Maximum mid_price |
| min_days_to_resolution integer | Min days until close_time |
| max_days_to_resolution integer | Max days until close_time |
| sort_by string | "volume", "volume_24h", "title", "price", "spread", "updated" (default: "volume") |
| sort_dir string | "asc" or "desc" (default: "desc") |
curl /api/markets?platform=polymarket&limit=5&sort_by=spread&sort_dir=asc
{
"markets": [
{
"id": 101,
"platform": "polymarket",
"title": "Bitcoin above $100k?",
"mid_price": 0.73,
"last_price": 0.73,
"spread": 0.02,
"volume": 850000,
"volume_24h": 45000,
"open_interest": null,
"floor_strike": null,
"strike_type": null,
"status": "active",
"category": "crypto",
"category_group": "Crypto",
"event_id": 42,
"resolved_outcome": null,
"resolved_at": null,
"final_price": null,
"resolution_criteria": "Resolves Yes if...",
"rules_secondary": null
}
],
"total": 1240,
"limit": 5,
"offset": 0
}
Get a single market by platform and platform-specific ID.
| platform string Required | "polymarket" or "kalshi" |
| platform_id string Required | Platform-specific market identifier |
curl /api/markets/polymarket/0x1234abcd
{
"id": 101,
"platform": "polymarket",
"platform_id": "0x1234abcd",
"title": "Bitcoin above $100k?",
"mid_price": 0.73,
"last_price": 0.73,
"yes_bid": 0.72,
"yes_ask": 0.74,
"spread": 0.02,
"volume": 850000,
"volume_24h": 45000,
"open_interest": null,
"floor_strike": null,
"strike_type": null,
"category_group": "Crypto",
"event_id": 42,
"event": {
"id": 42,
"title": "Will Bitcoin exceed $100k?"
}
}
Get price snapshots for a single market by database ID.
| market_id integer Required | Market database ID |
| hours integer | Lookback window in hours (default: 168 / 7 days) |
curl /api/markets/101/price-history?hours=72
{
"market_id": 101,
"snapshots": [
{
"captured_at": "2025-03-15T12:00:00Z",
"mid_price": 0.73,
"yes_bid": 0.72,
"yes_ask": 0.74,
"spread": 0.02,
"volume": 850000,
"volume_delta": 1200
}
]
}
Get price snapshots for multiple markets in one request. Accepts up to 1000 market IDs. Resolved markets return their last 1000 snapshots; active markets filter by the hours lookback window.
| market_ids integer[] Required | Array of market database IDs (max 1000) |
| hours integer | Lookback window in hours (default: 168 / 7 days) |
curl -X POST /api/markets/price-history/batch \
-H "Content-Type: application/json" \
-d '{"market_ids": [101, 205, 312], "hours": 72}'
{
"markets": [
{
"market_id": 101,
"snapshots": [
{
"captured_at": "2025-03-15T12:00:00Z",
"mid_price": 0.73,
"yes_bid": 0.72,
"yes_ask": 0.74,
"spread": 0.02,
"volume": 850000,
"volume_delta": 1200
}
]
},
{
"market_id": 205,
"snapshots": [...]
}
]
}
Get current data for multiple markets in one request. Useful for exit checking and position monitoring without per-market API calls. Max 1000 IDs.
| market_ids integer[] Required | Array of market database IDs (max 1000) |
curl -X POST /api/markets/batch \
-H "Content-Type: application/json" \
-d '{"market_ids": [101, 205, 312]}'
{
"markets": [
{
"id": 101,
"platform": "polymarket",
"title": "Will BTC exceed $100k by June?",
"mid_price": 0.73,
"status": "active",
"resolved_outcome": null,
"volume": 850000,
"event_id": 42
}
]
}
Get all cross-platform matched market pairs. Returns MATCH-validated pairs with computed price spread. Replaces per-event match lookups.
| min_volume number | Min volume on either market (default: 0) |
| min_spread number | Min cross-platform price spread |
| status string | "active" or "resolved" (both sides must match) |
| limit integer | Max results (default: 200, max: 500) |
| offset integer | Pagination offset (default: 0) |
curl /api/matches?min_volume=50000&status=active
{
"pairs": [
{
"market_a": {
"id": 101,
"platform": "polymarket",
"title": "BTC above $100k by June?",
"mid_price": 0.73,
"volume": 850000,
"status": "active",
"event_id": 42
},
"market_b": {
"id": 205,
"platform": "kalshi",
"title": "Bitcoin above $100,000 by June 30?",
"mid_price": 0.68,
"volume": 120000,
"status": "active",
"event_id": 42
},
"sim_3072": 0.96,
"llm_verdict": "MATCH",
"spread": 0.05
}
],
"total": 234,
"limit": 200,
"offset": 0
}
Search markets by semantic similarity. Uses embedding-based search to find markets related to your query text.
| text string Required | Search query text |
| top_k integer | Max results (default: 20) |
| min_volume number | Minimum volume filter |
| status string | "active" or "resolved" |
curl -X POST /api/markets/search \
-H "Content-Type: application/json" \
-d '{
"text": "federal reserve interest rate",
"top_k": 5,
"status": "active"
}'
{
"results": [
{
"id": 205,
"platform": "kalshi",
"title": "Fed cuts rates in June?",
"similarity": 0.91,
"mid_price": 0.45,
"volume": 320000
}
],
"count": 5,
"query": "federal reserve interest rate"
}
The API uses standard HTTP status codes. Error responses include a detail message.
| 400 | Bad request — invalid parameters |
| 401 | Unauthorized — missing or invalid API key |
| 404 | Not found — resource does not exist |
| 429 | Rate limited — too many requests (60/min) |
| 500 | Internal server error |
{
"detail": "Event not found"
}
Install the Bidweave Python SDK for typed access to all endpoints.
pip install bidweave
The SDK provides async and sync clients with automatic pagination, type hints, and error handling.
# pip install bidweave from bidweave import Bidweave client = Bidweave(base_url="https://swarm-1gnx.onrender.com") # List active events events = client.events(status="active", limit=10) for ev in events: print(f"{ev.title}: {ev.consensus_price:.0%}") # Search markets results = client.search("bitcoin price") for r in results: print(f"[{r.platform}] {r.title} ({r.similarity:.2f})") # Get price history history = client.event_prices(event_id=42) for market in history: print(f"{market.platform}: {len(market.snapshots)} points")