/api/public/forecast-availability
Check if Quotient already has a forecast for a market (free)
Free lookup for one market. Identify it with exactly one of market_key, market_id, or slug, and the response tells you what to do next. If Quotient already has a forecast, read points to where you can fetch it ($0.01). If it does not, generation is a ready-to-send request body for POST /api/auth/forecast-requests, which generates a new forecast ($1.00). If the market is a topic excluded from Quotient forecasting (sports outcomes, mention markets, short-horizon crypto up/down markets — fifteen-minute and hourly settles; daily-close and longer crypto horizons remain requestable), excluded explains why and generation is null. The response contains coverage metadata and read or generation pointers.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| market_key | query | string | Preferred canonical marketKey. Mutually exclusive with market_id and slug; do not also provide venue. Minimum length: 1; Maximum length: 512 |
| market_id | query | string | Venue-native market ID. Mutually exclusive with market_key and slug; venue is required. Minimum length: 1; Maximum length: 512 |
| slug | query | string | Market slug. Mutually exclusive with market_key and market_id; venue defaults to polymarket. Minimum length: 1; Maximum length: 512 |
| venue | query | "polymarket" | "polymarket_us" | "kalshi" | "limitless" | Optional prediction-market venue filter. Omit it on catalog/feed routes to include every covered venue. On legacy slug or condition-ID lookups, omission retains the Polymarket namespace; prefer marketKey for collision-safe cross-venue lookup. |
Responses
200: Free availability result and the next non-duplicative action
| Field | Type | Description | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| tracked required | boolean | Whether the market identity currently resolves to a Quotient Market row. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| available required | boolean | Whether a committed stored forecast exists. This check is free. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| market required | CanonicalMarketWithRelationships | null | market fields
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| question required | string | null | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| latestForecast required | object | null | Existence metadata only. Probability and research remain in the paid forecast response.latestForecast fields
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| read required | object | null | read fields
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| generation required | object | null | Null when a forecast already exists or when excluded is non-null.generation fields
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| targetResolution required | object | null | Non-null when the supplied Kalshi identifier names a multi-contract event. Resolve the endpoint and choose one exact child ticker before generation.targetResolution fields
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| excluded required | object | null | Non-null when Quotient will not schedule a forecast for this market. Sports outcomes, mention markets, and short-horizon crypto up/down markets (fifteen-minute and hourly settles; daily-close and longer crypto horizons stay in scope) are permanently out of scope; generation is null and POST /api/auth/forecast-requests returns 422 forecast_topic_excluded.excluded fields
|
422: Provide exactly one supported market identifier
| Field | Type | Description |
|---|---|---|
| error required | string | Error code |
| message required | string | Human-readable message |
| retry_after | integer | Seconds to wait (only on 429) |
| retryAfter | integer | Seconds to wait for owner-scoped forecast-request quota errors. |
| limit_scope | string | Quota scope that rejected the request, such as standard or x_research. |
| quotaScope | string | Stable forecast-request quota scope, such as venue_market_daily. |
| limit | integer | Configured bound for the forecast-request quota that was exceeded. |
503: Availability source temporarily unavailable
| Field | Type | Description |
|---|---|---|
| error required | string | Error code |
| message required | string | Human-readable message |
| retry_after | integer | Seconds to wait (only on 429) |
| retryAfter | integer | Seconds to wait for owner-scoped forecast-request quota errors. |
| limit_scope | string | Quota scope that rejected the request, such as standard or x_research. |
| quotaScope | string | Stable forecast-request quota scope, such as venue_market_daily. |
| limit | integer | Configured bound for the forecast-request quota that was exceeded. |
Set QUOTIENT_API_KEY in your shell and replace example identifiers with returned IDs before running a request.
curl --request GET \
'https://quotient-api-gateway.onrender.com/api/public/forecast-availability'{
"tracked": false,
"available": false,
"market": {
"venue": "polymarket",
"nativeMarketId": "example",
"nativeEventId": "example",
"seriesTicker": "example",
"marketKey": "example",
"quotientMarketId": "example",
"slug": "example",
"marketUrl": "example",
"sourceUrl": "example",
"broker_channels": [
"robinhood"
],
"robinhood_category": "example",
"robinhood_url": "example",
"relationships": {
"assets": [
{
"relationship": "HAS_MARKET",
"direction": "incoming",
"via": "direct",
"id": "example",
"assetKey": "example",
"name": "example",
"ticker": "example",
"asset_type": "example"
}
],
"markets": [
{
"relationship": "HAS_MARKET",
"direction": "incoming",
"via": "direct",
"marketKey": "example",
"venue": "polymarket",
"nativeMarketId": "example",
"question": "example"
}
],
"signals": [
{
"relationship": "HAS_MARKET",
"direction": "incoming",
"via": "direct",
"id": "example",
"signal_type": "prediction_market",
"canonical_endpoint": "/api/v1/signals",
"side": "example",
"published_at": "example"
}
],
"truncated": {
"assets": false,
"markets": false,
"signals": false
}
}
},
"question": "example",
"latestForecast": {
"id": "example",
"createdAt": "2027-01-01T00:00:00Z",
"relationships": {
"assets": [
{
"relationship": "HAS_MARKET",
"direction": "incoming",
"via": "direct",
"id": "example",
"assetKey": "example",
"name": "example",
"ticker": "example",
"asset_type": "example"
}
],
"markets": [
{
"relationship": "HAS_MARKET",
"direction": "incoming",
"via": "direct",
"marketKey": "example",
"venue": "polymarket",
"nativeMarketId": "example",
"question": "example"
}
],
"signals": [
{
"relationship": "HAS_MARKET",
"direction": "incoming",
"via": "direct",
"id": "example",
"signal_type": "prediction_market",
"canonical_endpoint": "/api/v1/signals",
"side": "example",
"published_at": "example"
}
],
"truncated": {
"assets": false,
"markets": false,
"signals": false
}
}
},
"read": {
"method": "GET",
"endpoint": "example",
"paid": true
},
"generation": {
"method": "POST",
"endpoint": "/api/auth/forecast-requests",
"authentication": "x-quotient-api-key",
"idempotencyKeyRequired": true,
"body": {
"kind": "venue_market",
"venue": "polymarket",
"market_id": "example"
}
},
"targetResolution": {
"endpoint": "example",
"reason": "venue_event_requires_market",
"message": "example",
"marketCount": 1
},
"excluded": {
"reason": "sports",
"message": "example"
}
}