Skip to main content

Overview

The Forecasts endpoints allow you to submit predictions on questions and withdraw existing forecasts. All forecasts are submitted as arrays to support single questions, groups of questions, and conditional questions in a unified interface.
Before submitting forecasts, retrieve the question details from /api/posts/{postId}/ or /api/questions/{questionId}/ to understand the question type, bounds, and current status.

Submit Forecasts

curl -X POST "https://www.metaculus.com/api/questions/forecast/" \
  -H "Authorization: Token YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '[{
    "question": 1,
    "probability_yes": 0.63
  }]'
POST /api/questions/forecast/ Submit one or more forecasts. The request body must always be an array, even for single questions.

Request Body

The request body is an array of forecast objects. The structure depends on the question type:

Binary Questions

question
integer
required
The question ID
probability_yes
number
required
Probability between 0 and 1 that the answer is “yes”
end_time
string (datetime)
Optional: When to automatically withdraw this forecast

Multiple Choice Questions

question
integer
required
The question ID
probability_yes_per_category
object
required
Object mapping option names to probabilities. Values must sum to 1.0.Example:
{
  "Democratic": 0.5,
  "Republican": 0.3,
  "Other": 0.2
}
end_time
string (datetime)
Optional: When to automatically withdraw this forecast

Continuous Questions (Numeric, Date, Discrete)

question
integer
required
The question ID (must be the question ID, not the post ID)
continuous_cdf
array
required
Array of CDF values. Length depends on inbound_outcome_count (default: 201 values for continuous, 11 for discrete with 10 outcomes).Important CDF Requirements:
  1. Strictly Increasing: Each value must be at least 0.00005 (0.01/200) greater than the previous value
  2. Maximum Step: No step can increase by more than 0.2 (or scaled based on outcome count)
  3. Boundary Conditions:
    • Closed lower bound: First value must be 0.0
    • Open lower bound: First value must be ≥ 0.001
    • Closed upper bound: Last value must be 1.0
    • Open upper bound: Last value must be ≤ 0.999
See the OpenAPI spec documentation for helper functions to generate valid CDFs.
end_time
string (datetime)
Optional: When to automatically withdraw this forecast

Conditional Questions

For conditional questions, submit forecasts for both the “if yes” and “if no” scenarios:
[
  {
    "question": 21477,
    "probability_yes": 0.499
  },
  {
    "question": 21476,
    "probability_yes": 0.501
  }
]

Group of Questions

For groups, submit a forecast for each question in the group:
[
  { "question": 10880, "probability_yes": 0.11 },
  { "question": 10923, "probability_yes": 0.22 },
  { "question": 10924, "probability_yes": 0.33 }
]

Response

201 Created
Empty object
Forecasts submitted successfully
400 Bad Request
object
Invalid request format or validation error
error
string
Error description
405 Method Not Allowed
object
Question is not open for forecasting
error
string
Reason why forecasting is not allowed

Continuous CDF Guidelines

Generating Valid CDFsCreating a valid CDF can be tricky. Here are the key steps:
  1. Check question scaling: Look at question.scaling to get range_min, range_max, zero_point, and boundary settings
  2. Determine your percentiles: Identify key percentiles of your belief (e.g., 5th, 25th, 50th, 75th, 95th)
  3. Generate the CDF: Linearly interpolate between your percentiles
  4. Standardize: Add a small uniform component to ensure monotonicity
See the OpenAPI spec for complete Python helper functions.

Example: Binary Forecast

[
  {
    "question": 1,
    "probability_yes": 0.75
  }
]

Example: Numeric Forecast

[
  {
    "question": 3530,
    "continuous_cdf": [
      0.0000, 0.0001, 0.0002, ...198 more values..., 0.9998, 0.9999, 1.0000
    ]
  }
]

Example: Discrete Forecast (10 outcomes)

[
  {
    "question": 1234,
    "continuous_cdf": [0, 0.05, 0.1, 0.15, 0.2, 0.35, 0.6, 0.75, 0.85, 0.95, 1.0]
  }
]

Withdraw Forecasts

curl -X POST "https://www.metaculus.com/api/questions/withdraw/" \
  -H "Authorization: Token YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '[{
    "question": 1
  }]'
POST /api/questions/withdraw/ Withdraw your current forecast(s) from one or more questions. This removes your prediction from the community aggregation going forward.

Request Body

question
integer
required
The question ID to withdraw from

Response

201 Created
Empty object
Forecast(s) withdrawn successfully
400 Bad Request
object
Invalid request format

Example: Withdraw from Multiple Questions

[
  { "question": 1 },
  { "question": 2 },
  { "question": 3 }
]

Important Notes

Forecast Validation
  • Questions must be in open status
  • Current time must be between open_time and scheduled_close_time
  • You must have forecaster permission on the question’s post
  • CDFs must be strictly monotonic and respect boundary conditions
Automatic WithdrawalsYou can set an end_time on forecasts to have them automatically withdrawn. This is useful for:
  • Testing temporary predictions
  • Setting expiring forecasts that represent near-term beliefs
  • Implementing time-based forecast strategies
Question IDs vs Post IDsAlways use the question ID in forecast submissions, not the post ID. For posts with single questions, these IDs are often the same, but for groups and conditionals, they differ. Get question IDs from the post details endpoint.

Build docs developers (and LLMs) love