Platform
Utility endpoints for server time, health checks, platform configuration, and browsing markets and events. No authentication required unless noted.
Server Time
GET /v1/time
Returns the server's current Unix timestamp. Use this to synchronize your clock for HMAC signature generation.
Response
{
"time": 1709136000
}
Health Check
GET /health
Returns the platform health status. Note: this endpoint is at the root path, not under /v1.
Response
{
"status": "ok"
}
Readiness Check
GET /ready
Returns readiness status including database and cache connectivity. Returns 503 if the database or cache is unreachable.
Response
{
"status": "ready"
}
Polygon Health
GET /health/polygon
Returns Polygon chain connectivity status.
Response
{
"status": "connected"
}
Platform Config
GET /v1/platform/config
Returns platform configuration including contract addresses and chain ID. This is the source of truth for every contract address your client needs to sign or settle orders. Cache the response per trading session and re-fetch on every deploy of your client; the API always returns the addresses currently in force.
Response
{
"chain_id": 137,
"exchange_address": "0xc183e918d9b1276b3e0037c4d66c8d25748a791f",
"market_factory_address": "0x86f3bf211c2424e0b602e22cd8fb5b3cab068d50",
"usdc_address": "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
"ctf_address": "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045",
"fee_sweeper_address": "0x91426bbab3e2cb0deec8e2ec47c58aed1d022950",
"outcome_slot_count": 2
}
fee_sweeper_address reflects the cutover-resolved FeeSweeper binding — FeeSweeper-1.2.0 post-V6-cutover, FeeSweeper-1.1.0 on V5, and the zero address when no FeeSweeper is configured. SDKs that read fees off-chain should consult this rather than hard-coding the FeeSweeper address.
outcome_slot_count is constant — all 4rho markets are binary (2-outcome). Surfaced here so SDK consumers migrating off the deprecated /v1/chain/config (sunset 2026-08-20) see the same field on the canonical successor.
Deprecated: /v1/chain/config
⚠️ Deprecated 2026-05-23. Sunset 2026-08-20. Use
/v1/platform/config(above) instead.
GET /v1/chain/config predates this endpoint. It returns the same cutover-aware contract addresses but under a different, narrower top-level shape and lacks the pause flags + fee-sweeper + volume metrics. As of 2026-05-23 every response carries the following standards-compliant deprecation headers — any HTTP client that respects them (curl -v, axios + interceptor, every modern monitoring agent) will surface the migration requirement automatically:
| Header | Value |
|---|---|
Deprecation | true (RFC 9745) |
Sunset | Wed, 20 Aug 2026 00:00:00 GMT (RFC 8594) |
Link | </v1/platform/config>; rel="successor-version" (RFC 8288) |
Warning | 299 - "Deprecated API. Use /v1/platform/config. Sunset 2026-08-20." (RFC 7234 §5.5) |
Key-name mapping for the migration:
/v1/chain/config (deprecated) | /v1/platform/config (canonical) |
|---|---|
chain_id | chain_id |
exchange | exchange_address |
market_factory | market_factory_address |
ctf | ctf_address |
collateral | usdc_address |
outcome_slot_count | outcome_slot_count |
default_fee_bps | platform_fee_bps |
| — | fee_sweeper_address |
| — | paused, market_factory_paused |
| — | total_markets, total_volume, total_fees_collected |
After 2026-08-20 the deprecated endpoint will be removed and clients still calling it will receive a 404. Migrate now — the canonical endpoint returns the same addresses today.
The example above shows the live mainnet addresses as of 2026-05-23 (V6 cutover, replacing the V5 set live 2026-05-04 → 2026-05-23). These are not constants — they rotate whenever the operator deploys a new Exchange or MarketFactory. Hard-coding any of them in client code means orders silently break at the next cutover with INVALID_SIGNATURE (the EIP-712 typehash includes verifyingContract).
Migration policy
When a contract address changes, the rollout is atomic from the API client's perspective:
- The new contract is deployed and funded.
GET /v1/platform/configflips to the new address. The order verifier on the API switches to the new EIP-712 domain in the same deploy.- From the cutover instant, orders signed against the freshly-fetched address are accepted; orders signed against the old address are rejected as
INVALID_SIGNATURE. - The previous contract remains read-only for settlement of orders signed before the cutover. There is no quiet period and no overlap window.
If you receive INVALID_SIGNATURE on a freshly-signed order, refresh /v1/platform/config — that's the load-bearing signal that your cached address is stale.
Sports Taxonomy
GET /v1/sports/taxonomy
Returns the sports taxonomy tree (leagues, teams, categories).
Response
{
"sports": [
{
"name": "Basketball",
"leagues": [
{
"name": "NBA",
"teams": ["Lakers", "Celtics"]
}
]
}
]
}
On-Chain Probabilities
GET /v1/onchain/market-probabilities
Returns current market probabilities derived from on-chain order book data.
Response
{
"probabilities": {
"market-id-1": [0.52, 0.48],
"market-id-2": [0.70, 0.30]
}
}
List Markets
GET /v1/markets
Returns markets on the platform. All markets are binary (2 outcomes); soccer 3-way markets are modeled as three separate binaries grouped by event_id.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
status | string | Filter by status (active, settled, pending, …) |
category | string | Filter by top-level category (e.g. Sports, Crypto, Politics) |
source_platform | string | Filter by upstream provider (kalshi, polymarket) |
search | string | Full-text search |
limit | int | Max results (default 20, max 100) |
offset | int | Pagination offset |
Response
{
"markets": [
{
"id": "475420a3-e775-4b70-9ad3-05c4fe5f8aa4",
"event_id": "62b29bda-97c3-426b-be05-52cbeb973acb",
"title": "Bobby Witt Jr.: 1+ home runs?",
"subtitle": "Bobby Witt Jr.: 1+",
"description": "If Bobby Witt Jr. records 1+ home runs in Los Angeles A vs Kansas City professional baseball game…",
"status": "active",
"resolution_type": "binary",
"outcomes": ["Bobby Witt Jr.: 1+", "No"],
"outcome_probabilities": [16, 84],
"previous_outcome_probabilities": [18, 82],
"category": "Sports",
"subcategories": ["Baseball"],
"external_source": "kalshi",
"external_event_id": "KXMLBHR-26APR261920LAAKC",
"external_market_type": "player_prop",
"series_ticker": "KXMLBHR",
"player_name": "Bobby Witt Jr.",
"player_team_abbrev": "KCB",
"stat_category": "home_runs",
"period": "full_game",
"line": "1",
"trading_starts_at": "2026-04-26T13:29:19.037144Z",
"trading_ends_at": "2026-04-29T23:20:00Z",
"resolution_source": "https://kalshi.com/markets/kxmlbhr/kxmlbhr/kxmlbhr-26apr261920laakc",
"settlement_sources": [
{ "name": "MLB", "url": "https://www.mlb.com" }
],
"open_interest": 4231,
"volume_24h": 18920,
"total_volume": "0",
"fee_bps": 50,
"deploy_status": "not_deployed",
"current_prices": { "0": 0.16, "1": 0.84 },
"created_at": "2026-04-26T13:29:19.037150Z",
"updated_at": "2026-04-26T13:29:19.037150Z"
}
],
"total": 1906624,
"limit": 20,
"offset": 0
}
MarketResponse fields
Pricing, taxonomy, and provenance fields surfaced on every market. Fields marked
optional are omitted (not null) when absent.
| Field | Type | Description |
|---|---|---|
id | uuid | Internal market identifier. |
event_id | uuid (optional) | Groups related markets (e.g., the three soccer outcome markets for one fixture). |
title, subtitle | string | Display strings. |
description | string | Long-form description / resolution criteria. |
status | string | active, pending, resolved, settled, cancelled. |
resolution_type | string | Always binary today. |
outcomes | string[] | Outcome labels — index 0 is YES, index 1 is NO. |
outcome_probabilities | int[] (optional) | Probabilities as 0–100 integers. [16, 84] means 16% YES, 84% NO. Convert to American odds client-side. |
previous_outcome_probabilities | int[] (optional) | Last-known probabilities before the most recent sync — use to draw price-change indicators. |
category | string | Top-level category. Title-cased (e.g. Sports, Crypto, Politics). Derived from upstream series.category for Kalshi. |
subcategories | string[] (optional) | Provider-supplied taxonomy tags. Example: ["Hockey"], ["US Elections", "Governor"]. Empty/omitted when the upstream lacks them. |
external_source | string | kalshi, polymarket, 4rho. |
external_event_id | string (optional) | Upstream identifier (e.g. Kalshi market ticker KXMLBHR-26APR261920LAAKC). |
external_market_type | string (optional) | Provider-side market kind (player_prop, moneyline, spread, total, other). |
series_ticker | string (optional) | Kalshi series ticker. Stable across reschedulings. |
player_name, player_team_abbrev, stat_category, period, line | string / string (optional) | Sports-prop attributes — present only on player-prop markets. |
trading_starts_at | ISO 8601 timestamp | UTC. Orders rejected before this. |
trading_ends_at | ISO 8601 timestamp | UTC. Order book closes at this time. |
resolved_at, settled_at | ISO 8601 timestamp (optional) | UTC. Set when the market resolves on-chain / payouts settle. |
resolution_source | string (optional) | URL to the canonical upstream market (e.g. the original Kalshi page). |
settlement_sources | {name, url}[] (optional) | Provider-cited resolution references — the "resolves via X" trust signal. Populated when the upstream exposes them (Kalshi sports series do; weather and binary-prediction series typically don't). |
open_interest | int (optional) | Open interest in whole contracts (currently-open positions on the upstream provider). Liquidity signal independent of cumulative trade volume. |
volume_24h | int (optional) | Trailing-24h trade volume on the upstream provider in whole units (whole contracts / whole USD), normalized identically across Kalshi and Polymarket. Distinct from cumulative total_volume. |
total_volume | string | Cumulative lifetime volume on 4rho (decimal string, USDC). |
fee_bps | int | Taker fee in basis points (50 = 0.5%). |
deploy_status | string | On-chain deploy state: not_deployed, pending_deploy, deploying, deployed, failed, permanently_failed. |
contract_address, condition_id, yes_token_id, no_token_id, question_id | string (optional) | Polygon / Gnosis CTF identifiers. Populated once deploy_status='deployed'. |
current_prices | { "0": number, "1": number } | Per-outcome mid prices (0–1). {0: 0.5, 1: 0.5} is the default 50/50 fallback when no on-chain liquidity exists yet. |
settlement_sources example
NHL game-line market (Kalshi KXNHL series):
{
"category": "Sports",
"subcategories": ["Hockey"],
"settlement_sources": [
{ "name": "NHL", "url": "https://www.nhl.com" }
]
}
Hourly crypto market with no settlement sources exposed:
{
"category": "Crypto",
"subcategories": ["Hourly", "BTC"],
"settlement_sources": null
}
When settlement_sources is empty/absent, fall back to resolution_source
(the upstream market URL) for provenance.
Get Market
GET /v1/markets/:id
Returns details for a single market. Response shape matches each entry in GET /v1/markets (see MarketResponse fields).
Market Metadata
GET /v1/markets/metadata
Returns market metadata including categories and counts.
Response
{
"categories": ["Sports", "Politics", "Crypto", "Soccer"],
"total_markets": 150,
"active_markets": 42
}
Categories are derived from upstream provider taxonomy
(series.category + series.tags for Kalshi) — they're not a hardcoded
list. New categories appear as upstream coverage expands.
Price History
GET /v1/markets/:id/history
Returns price history time series for a market.
Response
{
"market_id": "market-id-1",
"history": [
{"timestamp": "2024-01-15T00:00:00Z", "price": 0.50},
{"timestamp": "2024-01-16T00:00:00Z", "price": 0.52}
]
}
Market Trades
GET /v1/markets/:id/trades
Returns recent trades for a specific market.
Response
{
"trades": [
{
"id": "trade-id-1",
"price": "0.52",
"amount": "1000000",
"side": "BUY",
"timestamp": "2024-01-15T12:00:00Z"
}
]
}
Deploy Market
POST /v1/markets/:id/deploy
Scope: trade:orders
Request on-chain deployment for a market. Triggers operator gas spend.
Response
{
"status": "deploying",
"market_id": "market-id-1"
}
Outcome Tokens
Outcome tokens are ERC-1155 positions minted by the Gnosis CTF (ctf_address)
when a market is deployed. They are not exposed via a 4rho REST endpoint —
read them directly from chain. Each deployed market exposes its
yes_token_id and no_token_id on its MarketResponse,
which you pass to CTF.balanceOf(holder, tokenId) to query a position.
List Events
GET /v1/events
Returns all events on the platform. Events group related markets together.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
status | string | Filter by status |
category | string | Filter by category |
search | string | Full-text search |
limit | int | Max results (default 20, max 100) |
offset | int | Pagination offset |
Response
{
"events": [
{
"id": "62b29bda-97c3-426b-be05-52cbeb973acb",
"slug": "us-election-2024",
"title": "2024 US Presidential Election",
"description": "…",
"status": "active",
"category": "Politics",
"sport_league": null,
"sport_teams": null,
"image_url": null,
"start_time": "2026-11-03T00:00:00Z",
"external_event_id": "KXPRES-2024",
"external_platform": "kalshi",
"external_event_subtitle": null,
"external_event_mutually_exclusive": true,
"market_count": 5,
"created_at": "2024-01-10T00:00:00Z",
"updated_at": "2026-05-23T00:00:00Z"
}
],
"total": 1234,
"limit": 20,
"offset": 0
}
external_event_mutually_exclusive is the upstream-asserted multi-market
exclusivity flag — used to drive carveouts in odds rendering on the client
(see the RFQ rules in Market Data). sport_teams
is populated only for sports events.
Browse Events
GET /v1/events/browse
The primary endpoint for the event listing page — adds per-event market
aggregates (market_count_tradeable, volume_24h, open_interest,
featured_market, grouped market_groups) on top of the List Events
shape. Use this when rendering an events grid; use plain /v1/events when
you only need event metadata.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
status | string | Filter by status (active, pending, settled, …) |
category | string | Filter by top-level category |
search | string | Full-text search |
sort | string | volume_24h | start_time | created_at (default) |
limit | int | Max results (default 20, max 100) |
offset | int | Pagination offset |
Response
Same envelope as /v1/events ({events, total, limit, offset}). Each event
adds these aggregate fields:
| Field | Type | Description |
|---|---|---|
market_count_total | int | Total markets attached to the event, regardless of deploy state. |
market_count_tradeable | int | Subset with live on-chain liquidity. Use to gate "tradeable" badges. |
market_type_count | int | Distinct external_market_type values (moneyline, spread, total, …). |
volume_24h | int | Trailing-24h trade volume across all markets in the event (upstream units). |
open_interest | int | Sum of open_interest across the event's markets. |
market_groups | object[] | Markets pre-grouped by external_market_type for tabbed rendering. |
featured_market | MarketResponse | Operator-picked headline market, surfaced for card thumbnails. |
home_player_full_name, away_player_full_name | string (optional) | Set on sports events that resolve to a head-to-head matchup. |
Get Event
GET /v1/events/:slug
Returns details for a single event, including its markets.
Response
{
"slug": "us-election-2024",
"title": "2024 US Presidential Election",
"status": "active",
"markets": [
{
"id": "market-id-1",
"title": "Will candidate X win?",
"status": "active",
"outcomes": ["Yes", "No"]
}
],
"created_at": "2024-01-10T00:00:00Z"
}
Get Event View
GET /v1/events/:slug/view
Returns a rich event view including markets, metadata, and live scores (for sports events).