Skip to content

Prediction Markets Reports API ​

Retrieve Octagon's research reports for prediction markets directly over REST — pull an event's report and its recent versions, get its Trust Index scorecard, or trigger fresh report generation and check its status, without going through the Prediction Markets Agent.

The report body is the same markdown research memo the agent produces.

Field style, timestamps, and probability scales follow the Conventions. Base URL:

text
https://api.octagonai.co/v1

Endpoints ​

Each marketplace has its own endpoints, addressed by that marketplace's native event key.

MethodPathDescriptionCredits
GET/predictions/reports/kalshi/{event_ticker}Report versions for a Kalshi eventFree
GET/predictions/reports/polymarket/{event_slug}Report versions for a Polymarket eventFree
GET/predictions/reports/kalshi/{event_ticker}/trustTrust Index scorecard for a Kalshi eventFree
GET/predictions/reports/polymarket/{event_slug}/trustTrust Index scorecard for a Polymarket eventFree
POST/predictions/reports/kalshi/{event_ticker}Generate a fresh Kalshi report (asynchronous)3
POST/predictions/reports/polymarket/{event_slug}Generate a fresh Polymarket report (asynchronous)3
GET/predictions/reports/status/{run_id}Status of a generation run (no report body)Free

Credits per call are listed above. See the Prediction Markets Agent for plan eligibility.

Event Keys ​

EndpointsKeyExample
/reports/kalshi/…Event tickerKXBTC-25DEC31
/reports/polymarket/…Event slugfed-decision-in-september

Address markets by event key. The Prediction Markets Agent also accepts market URLs.

Retrieve Report Versions ​

text
GET /predictions/reports/kalshi/{event_ticker}
GET /predictions/reports/polymarket/{event_slug}

Returns one version of the event's report — the latest by default — with the event's recent versions, newest first. Each version is one analysis run.

Query Parameters ​

ParameterTypeRequiredDescription
versionstringNolatest (the default) for the newest version, or a run_id to pin that version. Any run_id the event produced resolves, including one older than the listed versions.

Response Fields ​

FieldTypeDescription
event_tickerstringThe resolved event key.
venuestringkalshi or polymarket, matching the endpoint called.
requested_urlstring | nullThe resolved market URL on the marketplace.
namestring | nullHuman-readable event name, as of the returned version.
titlestring | nullSame as name.
versionsarrayRecent versions, newest first (up to 6). Empty when nothing has been generated yet.
run_idstring | nullThe returned version: the latest, or the one version pins. null when nothing has been generated.
markdown_reportstring | nullThat version's full report as markdown.
trust_scorefloat | nullThat version's Trust Index score (0–100). The full scorecard is at Get the Trust Index.
trust_labelstring | nullThat version's Trust Index label: Strong, Good, Caution, High Risk, or Avoid.
outcome_probabilities_jsonstring | nullThat version's per-market probability breakdown, as a JSON string. Items carry model_probability_source and evidence_grade — see Interpreting the model probability.

Each entry in versions is that run's headline:

FieldTypeDescription
run_idstring (UUID)The run that produced this version. Pass it back as ?version=.
captured_atstringWhen the snapshot was captured.
analysis_last_updatedstringWhen the underlying analysis was last refreshed.
market_probabilityfloatMarket-implied probability.
model_probabilityfloatOctagon model probability.
confidence_scorefloatOctagon's confidence in the model output.
total_volumefloatTotal trading volume at capture time.
key_takeawaystringOne-line summary of the analysis.
trust_scorefloat | nullTrust Index score for this version (0–100).
trust_labelstring | nullTrust Index label for this version.

A version is a completed analysis, so versions[0] is always the latest report.

Status Codes ​

StatusMeaning
200The event key resolved. versions may be empty when nothing has been generated for it yet.
400Malformed event key, or an unknown query parameter (invalid_value).
404The event key matches nothing, or ?version=<run_id> is not a version of the event (not_found).

Get the Trust Index ​

text
GET /predictions/reports/kalshi/{event_ticker}/trust
GET /predictions/reports/polymarket/{event_slug}/trust

Returns the Trust Index scorecard for one report version. The Trust Index rates how far a market's price can be relied on, as an overall score blended from two axes: Integrity (market integrity, information fairness, resolution quality) and Trade quality (liquidity, move quality, rule clarity). The report response carries the headline as trust_score and trust_label.

Query Parameters ​

ParameterTypeRequiredDescription
versionstringNolatest (the default) or a run_id. Names the same version as on Retrieve Report Versions.
expandstringNoComma-separated axes to return in depth: integrity, trade_quality. See Expanded detail.

Response Fields ​

FieldTypeDescription
event_tickerstringThe resolved event key.
venuestringkalshi or polymarket, matching the endpoint called.
titlestring | nullHuman-readable event name, as of the scored version.
run_idstring (UUID)The version the scorecard belongs to.
trust_indexobjectThe scorecard.

trust_index:

FieldTypeDescription
scoreintegerOverall score, 0–100.
labelstringStrong, Good, Caution, High Risk, or Avoid.
computed_atstringWhen the scorecard was computed. The latest version's scorecard is refreshed hourly.
versionstringCalculation version.
capsarrayCaps that lowered the score, in the order applied: key, name, floor, ceiling. The last one set the score.
uncapped_scoreinteger | nullThe blended score before caps, when a cap lowered it.
floors_breachedarrayPillars under their safety floor whose cap changed nothing, because the score was already below its ceiling: key, floor, score.
profileobjectThe two axes, integrity and trade_quality.

profile.integrity:

FieldTypeDescription
key, namestring, stringAlways integrity and Integrity.
score, labelinteger, stringThe axis score and its label. Both null when the axis has no reading.
riskobject | nullIntegrity risk exposure: score (0–100, higher is more exposed) and label.
breakdownarrayThe three pillars, always in this order: manipulation_resistance (Market integrity), information_fairness (Info fairness), settlement_reliability (Resolution quality). Each has key, name, score, label, basis, summary, and factors.
screen_countsobject | nullIntegrity screens by state: run, not_applicable, awaiting_data.

A pillar's basis is measured when screens applied, or structural_prior when none did and the score comes from the market's structure.

profile.trade_quality:

FieldTypeDescription
key, namestring, stringAlways trade_quality and Trade quality.
score, labelinteger, stringThe axis score and its label. Both null when the axis has no reading.
basis, summary, factorsstring, string, arrayHow the score was reached, as on the integrity pillars. factors includes the cost of a $1,000 order.
breakdownarrayThe three components, always in this order: liquidity, move_quality, rule_clarity. Each has key, name, score, and label.

Every pillar and component is always listed. One without a reading has score and label set to null. Match caps and breached floors to pillars by key.

json
{
  "event_ticker": "KXPRESPERSON-28",
  "venue": "kalshi",
  "title": "2028 U.S. Presidential Election winner?",
  "run_id": "6f1d2c3a-8b4e-4f0a-9c7d-2e5b1a0f3c9d",
  "trust_index": {
    "score": 40, "label": "High Risk",
    "computed_at": "2026-09-22T12:50:39Z", "version": "underwriting_v1.4",
    "caps": [{ "key": "manipulation_resistance", "name": "Market integrity", "floor": 30, "ceiling": 40 }],
    "uncapped_score": 48,
    "floors_breached": [],
    "profile": {
      "integrity": {
        "key": "integrity", "name": "Integrity", "score": 46, "label": "High Risk",
        "risk": { "score": 82, "label": "High exposure" },
        "breakdown": [
          { "key": "manipulation_resistance", "name": "Market integrity", "score": 20, "label": "Avoid",
            "basis": "measured", "summary": "…", "factors": ["…"] },
          { "key": "information_fairness", "name": "Info fairness", "score": 40, "label": "High Risk", "…": "…" },
          { "key": "settlement_reliability", "name": "Resolution quality", "score": 92, "label": "Strong", "…": "…" }
        ],
        "screen_counts": { "run": 6, "not_applicable": 1, "awaiting_data": 3 },
        "screens": null, "structure_classes": null
      },
      "trade_quality": {
        "key": "trade_quality", "name": "Trade quality", "score": 60, "label": "Caution",
        "basis": "measured", "summary": "…", "factors": ["$1,000 order: ~2.1% cost", "…"],
        "breakdown": [
          { "key": "liquidity", "name": "Liquidity", "score": 80, "label": "Deep" },
          { "key": "move_quality", "name": "Move quality", "score": 65, "label": "Mostly confirmed" },
          { "key": "rule_clarity", "name": "Rule clarity", "score": 100, "label": "Clear" }
        ],
        "markets": null, "exclusions": null
      }
    }
  }
}

Expanded detail ​

expand deepens an axis; both axes are always present. A detail that wasn't expanded is null.

expandAdds
integrityprofile.integrity.screens: one entry per integrity screen, with key, state (run, not_applicable, or awaiting_data), score, label, confidence, drivers, evidence (text, window), and warning. Also profile.integrity.structure_classes.
trade_qualityprofile.trade_quality.markets: one card per scored market, with market_ticker, title, is_primary, last_trade_cents, and scores for market_quality, liquidity, move_quality, and resolution_clarity. Each score has score, label, confidence, not_applicable, drivers, evidence, and warning. Also profile.trade_quality.exclusions: markets left out of the read, as total, terminal_lifecycle, below_volume_floor, and no_ticker.

Status Codes ​

StatusCodeMeaning
200The scorecard for the requested version.
400invalid_valueMalformed event key, an unknown expand value, or an unknown query parameter.
404report_not_foundThe event key matches nothing, or no report has been generated yet.
404version_not_found?version=<run_id> is not a version of the event.
404trust_index_not_foundThe version exists but has no Trust Index.

Generate a Fresh Report ​

text
POST /predictions/reports/kalshi/{event_ticker}
POST /predictions/reports/polymarket/{event_slug}

Triggers fresh report generation for a market. There is no request body — the market is identified entirely by the path. Generation is asynchronous. The request returns 202 Accepted immediately with a run_id.

Response Fields (202 Accepted) ​

FieldTypeDescription
run_idstring (UUID)The generation run. Poll GET /predictions/reports/status/{run_id} with it.
statusstringAlways "processing" on acceptance.
event_tickerstringThe resolved event key.
venuestringkalshi or polymarket, matching the endpoint called.

The 3-credit charge is applied when the 202 is returned. If generation subsequently fails, the credits are automatically refunded.

Requirements ​

  • Market status: the market must be open on the marketplace.

Errors ​

StatusCodeMeaning
400invalid_valueMalformed event key.
400kalshi_url_requiredNo event matches the key.
400kalshi_reference_ambiguousThe key matches multiple events.
401no_subscriptionNo active subscription on the API key.
403insufficient_planFresh generation requires a Plus, Pro, or Enterprise plan.
404kalshi_market_not_foundThe market could not be found on the marketplace.
409kalshi_market_not_openThe market is not open on the marketplace (expired).
429insufficient_creditsNot enough credits for the 3-credit charge.
503service_unavailableThe generation service could not be reached.

Errors use the envelope {"error": {"message", "type", "param", "code"}}.

Check a Run's Status ​

GET /predictions/reports/status/{run_id}

Returns the status of a generation run. Poll it after triggering fresh generation. When status is "completed", fetch the markdown from the marketplace endpoint using the returned venue and event_ticker, with ?version=latest or ?version=<run_id>.

ParameterTypeRequiredDescription
run_idstring (UUID)YesThe run ID returned by a POST to /reports.

Response Fields ​

FieldTypeDescription
run_idstring (UUID)The requested run.
statusstring"processing", "completed", or "failed".
venuestringkalshi or polymarket — which marketplace endpoint to fetch from.
event_tickerstring | nullThe resolved event key for the run.
requested_urlstring | nullThe resolved market URL for the run.

A known run always returns 200 — poll until status leaves "processing". A "failed" run means generation did not complete. 404 (not_found) means the run_id is unknown.

TIP

If you only need the report body as soon as it's ready, you can skip this endpoint and poll the marketplace endpoint with ?version=latest directly — markdown_report stays null until the new version lands.

Notes ​

  • Poll every 30–60 seconds; fresh generation typically takes several minutes.
  • The run_id returned by a POST is the single join key: use it to check run status, to pin a version on retrieval (?version=<run_id>), and to reconcile the credit charge.
  • The report markdown includes a Trust Index: <score> · <label> line. The full scorecard is at Get the Trust Index.