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:

HeaderValue
Deprecationtrue (RFC 9745)
SunsetWed, 20 Aug 2026 00:00:00 GMT (RFC 8594)
Link</v1/platform/config>; rel="successor-version" (RFC 8288)
Warning299 - "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_idchain_id
exchangeexchange_address
market_factorymarket_factory_address
ctfctf_address
collateralusdc_address
outcome_slot_countoutcome_slot_count
default_fee_bpsplatform_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:

  1. The new contract is deployed and funded.
  2. GET /v1/platform/config flips to the new address. The order verifier on the API switches to the new EIP-712 domain in the same deploy.
  3. From the cutover instant, orders signed against the freshly-fetched address are accepted; orders signed against the old address are rejected as INVALID_SIGNATURE.
  4. 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

ParameterTypeDescription
statusstringFilter by status (active, settled, pending, …)
categorystringFilter by top-level category (e.g. Sports, Crypto, Politics)
source_platformstringFilter by upstream provider (kalshi, polymarket)
searchstringFull-text search
limitintMax results (default 20, max 100)
offsetintPagination 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.

FieldTypeDescription
iduuidInternal market identifier.
event_iduuid (optional)Groups related markets (e.g., the three soccer outcome markets for one fixture).
title, subtitlestringDisplay strings.
descriptionstringLong-form description / resolution criteria.
statusstringactive, pending, resolved, settled, cancelled.
resolution_typestringAlways binary today.
outcomesstring[]Outcome labels — index 0 is YES, index 1 is NO.
outcome_probabilitiesint[] (optional)Probabilities as 0–100 integers. [16, 84] means 16% YES, 84% NO. Convert to American odds client-side.
previous_outcome_probabilitiesint[] (optional)Last-known probabilities before the most recent sync — use to draw price-change indicators.
categorystringTop-level category. Title-cased (e.g. Sports, Crypto, Politics). Derived from upstream series.category for Kalshi.
subcategoriesstring[] (optional)Provider-supplied taxonomy tags. Example: ["Hockey"], ["US Elections", "Governor"]. Empty/omitted when the upstream lacks them.
external_sourcestringkalshi, polymarket, 4rho.
external_event_idstring (optional)Upstream identifier (e.g. Kalshi market ticker KXMLBHR-26APR261920LAAKC).
external_market_typestring (optional)Provider-side market kind (player_prop, moneyline, spread, total, other).
series_tickerstring (optional)Kalshi series ticker. Stable across reschedulings.
player_name, player_team_abbrev, stat_category, period, linestring / string (optional)Sports-prop attributes — present only on player-prop markets.
trading_starts_atISO 8601 timestampUTC. Orders rejected before this.
trading_ends_atISO 8601 timestampUTC. Order book closes at this time.
resolved_at, settled_atISO 8601 timestamp (optional)UTC. Set when the market resolves on-chain / payouts settle.
resolution_sourcestring (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_interestint (optional)Open interest in whole contracts (currently-open positions on the upstream provider). Liquidity signal independent of cumulative trade volume.
volume_24hint (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_volumestringCumulative lifetime volume on 4rho (decimal string, USDC).
fee_bpsintTaker fee in basis points (50 = 0.5%).
deploy_statusstringOn-chain deploy state: not_deployed, pending_deploy, deploying, deployed, failed, permanently_failed.
contract_address, condition_id, yes_token_id, no_token_id, question_idstring (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

ParameterTypeDescription
statusstringFilter by status
categorystringFilter by category
searchstringFull-text search
limitintMax results (default 20, max 100)
offsetintPagination 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

ParameterTypeDescription
statusstringFilter by status (active, pending, settled, …)
categorystringFilter by top-level category
searchstringFull-text search
sortstringvolume_24h | start_time | created_at (default)
limitintMax results (default 20, max 100)
offsetintPagination offset

Response

Same envelope as /v1/events ({events, total, limit, offset}). Each event adds these aggregate fields:

FieldTypeDescription
market_count_totalintTotal markets attached to the event, regardless of deploy state.
market_count_tradeableintSubset with live on-chain liquidity. Use to gate "tradeable" badges.
market_type_countintDistinct external_market_type values (moneyline, spread, total, …).
volume_24hintTrailing-24h trade volume across all markets in the event (upstream units).
open_interestintSum of open_interest across the event's markets.
market_groupsobject[]Markets pre-grouped by external_market_type for tabbed rendering.
featured_marketMarketResponseOperator-picked headline market, surfaced for card thumbnails.
home_player_full_name, away_player_full_namestring (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).