Skip to main content
API-facing changes for Radion integrators. See the API overview for the current contract.
Entries tagged Breaking require changes to existing integrations. Review the migration notes before upgrading.
July 7, 2026
Events and markets use named list arrays and split detail routes
List endpoints for events and markets now return events and markets arrays instead of a shared data field. Detail endpoints now use separate paths for id-based and slug-based lookups.

Breaking

  • GET /v1/polymarket/events now returns { events, nextCursor }.
  • GET /v1/polymarket/markets now returns { markets, nextCursor }.
  • GET /v1/polymarket/events/{identifier} is replaced by /events/{event_id} for numeric ids and /events/slug/{event_slug} for slugs.
  • GET /v1/polymarket/markets/{identifier} is replaced by /markets/{condition_id} for condition ids and /markets/slug/{market_slug} for slugs. Numeric market ids are no longer accepted by the public REST route.

Migration

  • Replace res.data with res.events for events lists.
  • Replace res.data with res.markets for markets lists.
  • Send event slugs to /v1/polymarket/events/slug/{event_slug}.
  • Send market slugs to /v1/polymarket/markets/slug/{market_slug}.
  • Keep condition ids on /v1/polymarket/markets/{condition_id}.
July 5, 2026
Bare single-object responses; consistent list, search, and error shapes
Single-object endpoints no longer wrap their result in a data field. This is a breaking change for any code that reads res.data on a single object.

Changed

  • Single objects return bare: price, midpoint, spread, last-trade-price, orderbook, events/{id}, markets/{id}, auth/me, and POST /auth/keys. Read fields at the top level (res.price, not res.data.price).
  • data is now reserved for cursor-paged lists only (events, markets): { data: [...], nextCursor }.
  • GET /search returns the composite object bare: { events, themes, profiles, pagination }.
  • GET /auth/keys renames its array from data to keys: { keys, plan, trialEndsAt, monthlyUsage }.
  • Error bodies use camelCase: request_id is now requestId.

Migration

  • Single object: replace res.data with res (or read the field directly).
  • Search: replace res.data with res.
  • Keys list: replace res.data with res.keys.
  • Errors: read requestId instead of request_id.
July 3, 2026
New markets endpoints
Markets are now a first-class endpoint group, mirroring events. Data comes from the Polymarket Gamma catalog.

Added

  • GET /v1/polymarket/markets — list markets, cursor-paginated.
  • GET /v1/polymarket/markets/{identifier} — one market by condition id (0x…), numeric id, or slug.
  • Both are also exposed as the list_markets and get_market MCP tools.
July 3, 2026
Public JWT keys; paid plans lose the per-second rate limit
Public JWT keys let apps with no backend call Radion straight from the browser or a mobile client. A public key (pk_jwt_...) is safe to ship, and each request also carries a signed end-user token. Separately, per-second rate limiting was removed from all paid plans.

Added — public JWT keys

  • A new key type, pk_jwt_..., is safe to embed in a browser or mobile app. On its own it does nothing: every request must also send a signed user JWT in the Authorization: Bearer header.
  • Configure the key in the dashboard with a JWKS URL or an inline public key (PEM), plus optional aud / iss checks and a per-user rate limit.
  • Radion verifies the JWT signature, checks exp (and aud / iss when set), and rate-limits per user (sub). Monthly usage still counts against your plan.
  • Tokens must use an asymmetric algorithm (RS*, PS*, ES*, or EdDSA). Symmetric algorithms (HS256 and friends) are rejected.
  • Browser WebSocket clients that cannot set headers may pass api-key and token as query parameters on the /ws upgrade. See Authentication.

Breaking

  • requestsPerSecond in the GET /auth/me response is now null on paid plans. It stays a number on the free plan. Handle a nullable value.
July 2, 2026
Full-depth orderbook and dedicated price endpoints; lookup removed
The orderbook read model expanded from a single midpoint into full depth plus dedicated price endpoints. Search now paginates, events carry richer metadata, and two fields were removed.

Breaking — removed

  • GET /v1/polymarket/lookup. Use /search for fuzzy text search, or the id-scoped endpoints (/markets/{condition_id}, /markets/slug/{market_slug}, and the trader endpoints by address) for exact reads.
  • The expiresAt field from GET /auth/me. API keys do not expire.

Breaking — changed

  • GET /v1/polymarket/orderbook now returns full depth instead of only the midpoint. The response holds bids and asks arrays of { price, size } levels, plus lastTradePrice and tokenId. It still takes token_id. Read the midpoint from the new /midpoint endpoint.

Added

  • GET /v1/polymarket/midpoint — midpoint price for one outcome token. Takes token_id.
  • GET /v1/polymarket/price — best bid or ask price. Takes token_id and side (buy or sell).
  • GET /v1/polymarket/spread — bid-ask spread. Takes token_id.
  • GET /v1/polymarket/last-trade-price — last executed trade price. Takes token_id.

Changed

  • GET /v1/polymarket/search now returns a pagination object with hasMore and totalResults, and each profile includes createdAt. Query params are q, limit, and page.
  • GET /v1/polymarket/events and /events/{identifier} now return enriched metadata: ticker, subtitle, resolutionSource, image, icon, featuredImage, subcategory, seriesSlug, the active / closed / archived / new / featured / restricted flags, enableOrderbook, negRisk, competitive, volume24hr / volume1wk / volume1mo / volume1yr, commentCount, creationDate, closedTime, and the full markets array.
June 30, 2026
Trader profile, themes, and edge now populated from Polymarket
Trader endpoints now enrich responses with live Polymarket data instead of placeholders.

Added

  • GET /v1/polymarket/traders/{trader_id}/profile now returns a real identity (pseudonym, name, x username, verified badge, account created at) from the trader’s Polymarket public profile.
  • GET /v1/polymarket/traders/{trader_id}/themes now returns themeLeaderboard, eliteThemes, and avoidThemes aggregated from market tags; each per-market entry now carries the market slug.
  • GET /v1/polymarket/traders/{trader_id}/edge now fills bestEdgeConditions.themes.

Breaking — removed

  • The warnings.themeDataUnavailable field from the trader edge and themes responses.
June 28, 2026
On-chain read model replaces analysis and backtesting
Radion now serves Polymarket data from its own on-chain indexer instead of stored analysis snapshots. The analysis and backtesting products were removed and replaced by direct read-model endpoints for markets, traders, events, search, and the orderbook.

Breaking — removed

  • GET /v1/polymarket/markets/analysis and GET /v1/polymarket/markets/{slug}/analysis.
  • GET /v1/polymarket/traders/analysis and GET /v1/polymarket/traders/{id}/analysis.
  • All /v1/polymarket/backtesting/copytrading/* endpoints.
  • Response schema (component) names dropped the Dto suffix, e.g. TradeDtoTrade. This affects code generated from the OpenAPI schema.
  • Every single-object response is now wrapped in a data field, so all endpoints share one shape. GET /traders/{trader_id}/pnl, market detail, market-by-slug, orderbook, search, and event endpoints used to return the object on its own; read the value from data now.

Added

  • GET /v1/polymarket/markets — list markets by volume; plus /markets/{condition_id} and /markets/slug/{market_slug}.
  • GET /v1/polymarket/markets/{condition_id}/candlestick, /holders, and /trades.
  • GET /v1/polymarket/traders/{id}/trades, /positions, and /pnl.
  • GET /v1/polymarket/traders/{id}/profile, /performance, /risk, /edge, /distribution, and /themes — rebuilt on the on-chain read model. identity fields are null and theme grouping ships empty for now; /themes still returns best/worst markets by realized PnL, keyed by condition id.
  • GET /v1/polymarket/traders/global-pnl — PnL leaderboard.
  • GET /v1/polymarket/events and /events/{identifier}.
  • GET /v1/polymarket/search — venue-agnostic text search across events, topics, and profiles (proxied from Polymarket).
  • GET /v1/polymarket/lookup — exact lookup of a market or trader by id (condition id or address). This is the old /search behaviour, renamed.
  • GET /v1/polymarket/orderbook — live orderbook midpoint for one outcome token. The path is orderbook (one word, no hyphen) and takes token_id, not position_id.

Migration

  • Replace analysis reads with the on-chain endpoints: market metadata via /markets and /events, trader data via /traders/{id}/pnl, /positions, and /trades.
  • Drop backtesting calls; the copytrading simulator is no longer offered.
  • Regenerate any OpenAPI-derived client so schema names without the Dto suffix resolve.
  • Stop reading traderScore and confidence.score / rating from the performance response.
June 26, 2026
Hourly quotas replaced by per-second rate limits
Request throttling moved from an hourly quota to a per-second token bucket. Monthly quotas are unchanged. The burst is keyed by your account and shared across all keys.

Breaking

  • Hourly quotas are removed. Per-second rate limits are now Free: 5, Starter: 10, Pro: 50 requests/second. Enterprise stays uncapped.
  • GET /auth/me: hourlyLimit is renamed to requestsPerSecond.

Unchanged

  • Monthly quotas remain Free: 300, Starter: 3,000, Pro: 50,000 requests/month, shared across all keys and reset at the start of each UTC month.
  • Exceeding either limit still returns 429 Too Many Requests with a Retry-After header.
June 22, 2026
Renamed win rate, PnL, and volume fields; entry buckets are structured objects
Win rate and PnL shared one field name across endpoints while measuring different things. Trader analysis is lifetime (includes resolved-but-unclaimed positions and unrealized PnL); performance is realized-only over a trailing 365-day window. Fields were renamed so one name never means two computations. Entry-bucket fields became structured objects instead of raw price arrays.

Breaking — field renames

  • GET /v1/polymarket/traders/{trader_id}/performance: winRatetrailing365WinRate, realizedPnlrealized365Pnl (both: closed positions, trailing 365 days).
  • GET /v1/polymarket/traders/{trader_id}/analysis and the trader analyses list: winRatelifetimeWinRate, profitLosslifetimePnl (both: lifetime), medianVolumemedianPositionSizeUsd (value unchanged).
  • Market analysis topTraders[]: winRatelifetimeWinRate, profitLosslifetimePnl (same lifetime basis).

Breaking — entry buckets

  • GET /v1/polymarket/traders/{trader_id}/distribution: sweetSpotBucketsweetSpotBuckets and deadZoneBucketdeadZoneBuckets. Both changed from a nullable price array (number[] | null) to a required array of EntryBucket objects.
  • GET /v1/polymarket/backtesting/copytrading/jobs/{jobId}/summary: priceRange (number[] | null) → required bestBuckets (EntryBucket[]).
  • EntryBucket objects gained two required fields: realizedPnl and volumeUsd.

Migration

  • Update field reads to the new names. The two win rates and two PnL figures are not interchangeable — analysis values are lifetime (unclaimed + unrealized), performance values are realized over a trailing 365 days.
  • Read medianPositionSizeUsd instead of medianVolume; value and units (USD) unchanged.
  • Read bucket fields as EntryBucket objects, not price numbers, and drop null handling — these fields are now always present.
June 18, 2026
Trader category affinity renamed to theme affinity
Trader profile affinity now uses themes derived from Polymarket market tags instead of Polymarket’s legacy category field. The API naming changed from categories to themes.

Breaking

  • GET /v1/polymarket/traders/{trader_id}/categoriesGET /v1/polymarket/traders/{trader_id}/themes.
  • Response types and fields renamed: categoryLeaderboardthemeLeaderboard, eliteCategorieseliteThemes, avoidCategoriesavoidThemes.
  • Leaderboard and ROI entries now expose theme instead of category.
  • Warning field categoryDataUnavailablethemeDataUnavailable.
  • bestEdgeConditions.categoriesbestEdgeConditions.themes.

Migration

  • Call the /themes endpoint for trader theme affinity.
  • Update clients to read themeLeaderboard, eliteThemes, avoidThemes, theme, and themeDataUnavailable.
  • Update edge consumers to read bestEdgeConditions.themes.
June 15, 2026
API keys required, multi-key management, monthly limits, gated premium features
API access now requires an API key on every endpoint except GET /health. Dashboard key management supports multiple active keys, per-plan key caps, and shared monthly usage counters. Premium features are now enforced by plan.

Breaking

  • Unauthenticated API requests are no longer accepted. Send X-API-Key on every request except GET /health.
  • Plan names changed from signal / agent / custom to starter / pro / enterprise.
  • GET /auth/me now returns keyLabel instead of keyId, and may return plan: null for Free keys.
  • GET /v1/polymarket/markets/{slug}/analysis now returns { "data": [...] }. Without from, the array contains the latest snapshot as a single item.

Added

  • GET /auth/keys — list active keys for the signed-in dashboard user.
  • POST /auth/keys — create a key with a keyLabel. The raw key is returned once as rawKey.
  • DELETE /auth/keys/{keyLabel} — revoke an active key by label.
  • GET /auth/me and GET /auth/keys now expose monthly usage via monthlyUsage.used, monthlyUsage.limit, and monthlyUsage.resetsAt. GET /auth/me also includes hourlyLimit.
  • GET /v1/polymarket/markets/{slug}/analysis?from=YYYY-MM-DD returns historical snapshots computed on or after the date.

Changed

  • Hourly quotas are now Free: 50, Starter: 100, Pro: 1,000 requests, Enterprise: custom.
  • Monthly quotas are now enforced: Free: 300, Starter: 3,000, Pro: 50,000 requests, Enterprise: unlimited.
  • Monthly usage is shared across all keys for the same user. Extra keys do not create extra quota.
  • Active key caps are Free: 1, Starter: 3, Pro: 10, Enterprise: unlimited.
  • POST /v1/polymarket/backtesting/copytrading/run now requires Pro or Enterprise.
  • Historical market snapshots through the from parameter require Starter or higher.
  • Monthly quota exhaustion returns 429 Too Many Requests with detail: "Monthly request limit exceeded" and a Retry-After header pointing to the next monthly reset.

Migration

  • Create a free key from the dashboard and send it with X-API-Key on all API calls.
  • Update plan handling to use starter, pro, enterprise, or null for Free keys.
  • Read keyLabel instead of keyId from auth responses.
  • Update market-analysis-by-slug clients to read the first item of data when they need only the latest snapshot.
June 3, 2026
Backtesting summary warnings; auth profile endpoint renamed
Copytrading backtest jobs now continue when upstream price history is unavailable for individual tokens. Summary responses include warning metadata so you can detect degraded price-history coverage. The authenticated API key metadata endpoint was renamed to GET /auth/me.

Breaking

  • GET /auth/api-key was removed. Use GET /auth/me with the same X-API-Key header instead.

Changed

  • GET /auth/me returns the same API key metadata response shape that GET /auth/api-key returned.
  • GET /backtesting/copytrading/jobs/{jobId}/summary: completed jobs may include a warnings object with missingPriceHistoryTokenCount, totalTokenCount, and priceHistoryCoveragePct.
  • If price history is missing for some tokens, open-position valuation may be less precise. The simulator continues with its fallback pricing instead of failing the whole job.

Example

{
  "data": {
    "status": "done",
    "warnings": {
      "missingPriceHistoryTokenCount": 3,
      "totalTokenCount": 42,
      "priceHistoryCoveragePct": 92.86
    }
  }
}
June 2, 2026
API v1 namespace, cursor pagination, traderIds, stricter input validation
API endpoints are now available under the /v1 namespace. List endpoints use opaque cursor-based pagination. The copytrading backtest request field was renamed for multi-venue compatibility. All endpoints now validate input parameters and return structured errors on invalid input.

Breaking

  • GET /markets/analysis and GET /traders/analysis: the offset parameter is removed. Use cursor instead (omit on first request).
  • Response shape now includes nextCursor: { "data": [...], "nextCursor": "..." | null }.
  • POST /backtesting/copytrading/run: request field traderAddresses renamed to traderIds. The Ethereum-address format constraint was removed — any non-empty string up to 256 characters is accepted, supporting non-Ethereum venues.

Changed

  • Use /v1 as the canonical prefix for versioned analysis and backtesting requests, e.g. GET /v1/polymarket/markets/analysis.
  • Health and authentication endpoints stay at root: GET /health and GET /auth/api-key.
  • Existing unversioned routes such as GET /markets/analysis continue to work for now.
  • All endpoints now validate input. Invalid values return 400 Bad Request with a structured application/problem+json body.
  • GET /markets/{slug}/analysis: slug must be 1–200 chars.
  • GET /traders/{id}/analysis: id must be non-empty, max 256 chars.
  • GET /backtesting/copytrading/jobs/{jobId}/*: jobId must be a valid UUID.
  • GET /markets/analysis and GET /traders/analysis: default limit changed from 50 to 5, max limit from 100 to 10. offset is replaced by cursor-based pagination.

Deprecation notice

  • Unversioned endpoints are backward-compatible aliases and will be removed on June 16, 2026.

Migration

  • Update API clients to call analysis and backtesting endpoints under /v1/polymarket. Generic /v1/markets, /v1/traders, and /v1/backtesting paths are not served.
  • No request-body or response-body changes are required for the /v1/polymarket migration.
  • Remove offset from all requests to list endpoints.
  • Pass the nextCursor value from each response as the cursor parameter on the next request. Stop when nextCursor is null.
  • Update analysis list requests that set limit above 10. The default is now 5, and the maximum is now 10.
  • Rename traderAddresses to traderIds in all POST /backtesting/copytrading/run request bodies.
See Pagination for full details and code examples.
June 1, 2026
Trader metrics fields renamed and deduplicated
Trader metrics fields were renamed and deduplicated for consistency across trader-analysis and market top-trader responses.

Changed

  • walletMedianVolume on trader-analysis responses was renamed to medianVolume. Value and type unchanged.
  • The redundant positionCount field was removed from market top-trader entries. It always duplicated totalPositionCount.

Migration

  • Read medianVolume instead of walletMedianVolume wherever you consume trader-analysis responses.
  • Read totalPositionCount instead of positionCount on market top-trader entries.
May 30, 2026
Market analysis identifier field moved
Market analysis responses now expose the canonical venue-scoped market identifier only at market.id.

Changed

  • The top-level marketConditionId field was removed from market-analysis responses. Use market.id instead.
  • Request paths are unchanged. Continue to use market slugs in endpoints such as GET /markets/{slug}/analysis.

Migration

Update clients to read market.id instead of marketConditionId.
Before
{ "marketConditionId": "0xabcdef..." }
After
{ "market": { "id": "0xabcdef..." } }
May 19, 2026
Structured error responses
Error responses now return a structured JSON body following RFC 9457.

Changed

  • All error responses now return type, status, title, detail, and request_id with Content-Type: application/problem+json.
  • The 429 Too Many Requests response still includes a Retry-After header.

Migration

Update error handling to read detail and request_id instead of a flat error string.
Before
{ "error": "Invalid API key" }
After
{
  "type": "about:blank",
  "status": 401,
  "title": "Unauthorized",
  "detail": "Invalid API key",
  "request_id": "1748123456-1a"
}
May 18, 2026
Rate limiting on all endpoints
All API endpoints except GET /health now enforce hourly request quotas. Unauthenticated requests are allowed and count against the free-tier quota, keyed by IP address.

Quotas by plan

  • Free (no key): 10 requests/hour, keyed by IP address.
  • Signal: 100 requests/hour, keyed by API key.
  • Agent: 1,000 requests/hour, keyed by API key.
  • Custom: unlimited.

Behavior

  • Your full hourly quota is available immediately as a burst, then replenishes continuously through the hour.
  • Requests exceeding the quota receive 429 Too Many Requests with a Retry-After header.
May 13, 2026
Removed analysis run and status endpoints
The endpoints for creating on-demand analysis runs and checking their status were removed. Analysis snapshots are still available via the read endpoints.

Removed

  • POST /markets/{slug}/analysis
  • GET /markets/{slug}/analysis/status
  • POST /traders/{id}/analysis
  • GET /traders/{id}/analysis/status

Unchanged

  • GET /markets/{slug}/analysis — read the latest market analysis snapshot.
  • GET /traders/{id}/analysis — read the latest trader analysis snapshot.

Migration

Replace run-and-poll flows with direct reads. Analysis is now refreshed automatically.
Before
curl -X POST "https://api.radion.app/markets/will-trump-win-2024/analysis" \
  -H "X-API-Key: YOUR_API_KEY"
# then poll /analysis/status ...
After
curl "https://api.radion.app/markets/will-trump-win-2024/analysis" \
  -H "X-API-Key: YOUR_API_KEY"
April 10, 2026
Trader analysis transparency fields
Analysis responses now expose additional trader-history fields without changing route shapes or request parameters.

Added

  • winRate on trader-analysis responses and topTraders entries in market-analysis responses. Based on closed positions only.
  • latestPositionTimestamp on trader-analysis responses and topTraders entries in market-analysis responses.
Both fields may be null on older snapshots created before these fields were tracked.
April 8, 2026
Trader analysis endpoint
Radion’s API now separates featured-feed browsing, search, and analysis flows.

Added

  • GET /traders/{id}/analysis — read trader analysis snapshots.
  • venue query filtering for search and market-list flows. polymarket is the currently supported venue.
Last modified on July 7, 2026