> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/Metaculus/metaculus/llms.txt
> Use this file to discover all available pages before exploring further.

# Making Forecasts

> Complete examples of submitting forecasts via the Metaculus API

This guide shows you how to submit forecasts for different question types using the Metaculus API.

## Prerequisites

All API requests require authentication. Make sure you have:

1. Generated an API token from your [account settings](https://www.metaculus.com/accounts/settings/account/#api-access)
2. Include the token in the `Authorization` header: `Token YOUR_API_TOKEN`

## Binary Questions

Binary questions have yes/no outcomes. Submit a probability between 0 and 1.

<Steps>
  <Step title="Get the question details">
    First, retrieve the question to get its ID and confirm it's a binary question:

    <CodeGroup>
      ```python Python theme={null}
      import requests

      API_TOKEN = "your_api_token_here"
      headers = {"Authorization": f"Token {API_TOKEN}"}

      # Get post details
      post_id = 1
      response = requests.get(
          f"https://www.metaculus.com/api/posts/{post_id}/",
          headers=headers
      )
      post_data = response.json()
      question = post_data["question"]

      print(f"Question ID: {question['id']}")
      print(f"Type: {question['type']}")
      print(f"Title: {question['title']}")
      ```

      ```javascript JavaScript theme={null}
      const API_TOKEN = "your_api_token_here";
      const headers = { "Authorization": `Token ${API_TOKEN}` };

      // Get post details
      const postId = 1;
      const response = await fetch(
        `https://www.metaculus.com/api/posts/${postId}/`,
        { headers }
      );
      const postData = await response.json();
      const question = postData.question;

      console.log(`Question ID: ${question.id}`);
      console.log(`Type: ${question.type}`);
      console.log(`Title: ${question.title}`);
      ```

      ```bash cURL theme={null}
      curl -X GET "https://www.metaculus.com/api/posts/1/" \
        -H "Authorization: Token your_api_token_here"
      ```
    </CodeGroup>
  </Step>

  <Step title="Submit your binary forecast">
    Submit a probability for the yes outcome:

    <CodeGroup>
      ```python Python theme={null}
      import requests

      API_TOKEN = "your_api_token_here"
      headers = {"Authorization": f"Token {API_TOKEN}"}

      # Submit binary forecast
      forecast_data = [
          {
              "question": 1,  # Question ID
              "probability_yes": 0.63
          }
      ]

      response = requests.post(
          "https://www.metaculus.com/api/questions/forecast/",
          headers=headers,
          json=forecast_data
      )

      if response.status_code == 201:
          print("Forecast submitted successfully!")
      else:
          print(f"Error: {response.status_code}")
          print(response.json())
      ```

      ```javascript JavaScript theme={null}
      const API_TOKEN = "your_api_token_here";
      const headers = {
        "Authorization": `Token ${API_TOKEN}`,
        "Content-Type": "application/json"
      };

      // Submit binary forecast
      const forecastData = [
        {
          question: 1,  // Question ID
          probability_yes: 0.63
        }
      ];

      const response = await fetch(
        "https://www.metaculus.com/api/questions/forecast/",
        {
          method: "POST",
          headers: headers,
          body: JSON.stringify(forecastData)
        }
      );

      if (response.status_code === 201) {
        console.log("Forecast submitted successfully!");
      } else {
        console.log(`Error: ${response.status}`);
        console.log(await response.json());
      }
      ```

      ```bash cURL theme={null}
      curl -X POST "https://www.metaculus.com/api/questions/forecast/" \
        -H "Authorization: Token your_api_token_here" \
        -H "Content-Type: application/json" \
        -d '[{
          "question": 1,
          "probability_yes": 0.63
        }]'
      ```
    </CodeGroup>
  </Step>
</Steps>

## Numeric Questions (Continuous)

Numeric questions require a 201-point CDF (Cumulative Distribution Function). For detailed guidance on generating CDFs, see the [Continuous CDF Guide](/api/examples/continuous-cdf).

<Steps>
  <Step title="Get the question scaling">
    Retrieve the question details to understand its range and scaling:

    <CodeGroup>
      ```python Python theme={null}
      import requests

      API_TOKEN = "your_api_token_here"
      headers = {"Authorization": f"Token {API_TOKEN}"}

      # Get question details
      post_id = 3530
      response = requests.get(
          f"https://www.metaculus.com/api/posts/{post_id}/",
          headers=headers
      )
      question = response.json()["question"]

      print(f"Type: {question['type']}")
      print(f"Range: {question['scaling']['range_min']} to {question['scaling']['range_max']}")
      print(f"Unit: {question['unit']}")
      print(f"Open lower bound: {question['open_lower_bound']}")
      print(f"Open upper bound: {question['open_upper_bound']}")
      ```

      ```javascript JavaScript theme={null}
      const API_TOKEN = "your_api_token_here";
      const headers = { "Authorization": `Token ${API_TOKEN}` };

      // Get question details
      const postId = 3530;
      const response = await fetch(
        `https://www.metaculus.com/api/posts/${postId}/`,
        { headers }
      );
      const question = (await response.json()).question;

      console.log(`Type: ${question.type}`);
      console.log(`Range: ${question.scaling.range_min} to ${question.scaling.range_max}`);
      console.log(`Unit: ${question.unit}`);
      console.log(`Open lower bound: ${question.open_lower_bound}`);
      console.log(`Open upper bound: ${question.open_upper_bound}`);
      ```

      ```bash cURL theme={null}
      curl -X GET "https://www.metaculus.com/api/posts/3530/" \
        -H "Authorization: Token your_api_token_here"
      ```
    </CodeGroup>
  </Step>

  <Step title="Generate a CDF">
    Create a 201-point CDF. This example shows a simple approach:

    ```python Python theme={null}
    import numpy as np

    # For a question with closed bounds (range_min to range_max)
    # Generate a simple normal-like distribution
    def simple_cdf(mean_location=0.5, spread=0.3):
        """
        Generate a 201-point CDF.
        mean_location: center of distribution (0 to 1)
        spread: how spread out the distribution is
        """
        points = np.linspace(0, 1, 201)
        # Simple sigmoid-based CDF
        cdf = 1 / (1 + np.exp(-(points - mean_location) / spread))
        # Normalize to [0, 1]
        cdf = (cdf - cdf.min()) / (cdf.max() - cdf.min())
        return cdf.tolist()

    my_cdf = simple_cdf(mean_location=0.6, spread=0.15)
    print(f"CDF has {len(my_cdf)} points")
    print(f"First value: {my_cdf[0]:.5f}, Last value: {my_cdf[-1]:.5f}")
    ```

    <Note>
      For production use, see the [Continuous CDF Guide](/api/examples/continuous-cdf) for proper CDF generation that handles:

      * Linear and logarithmic scaling
      * Open and closed bounds
      * Percentile-based distributions
      * CDF standardization and validation
    </Note>
  </Step>

  <Step title="Submit your numeric forecast">
    Submit the CDF to the API:

    <CodeGroup>
      ```python Python theme={null}
      import requests

      API_TOKEN = "your_api_token_here"
      headers = {"Authorization": f"Token {API_TOKEN}"}

      # Submit continuous forecast
      forecast_data = [
          {
              "question": 3530,
              "continuous_cdf": my_cdf  # 201-point list
          }
      ]

      response = requests.post(
          "https://www.metaculus.com/api/questions/forecast/",
          headers=headers,
          json=forecast_data
      )

      if response.status_code == 201:
          print("Forecast submitted successfully!")
      else:
          print(f"Error: {response.status_code}")
          print(response.json())
      ```

      ```javascript JavaScript theme={null}
      const API_TOKEN = "your_api_token_here";
      const headers = {
        "Authorization": `Token ${API_TOKEN}`,
        "Content-Type": "application/json"
      };

      // Submit continuous forecast
      const forecastData = [
        {
          question: 3530,
          continuous_cdf: myCdf  // 201-point array
        }
      ];

      const response = await fetch(
        "https://www.metaculus.com/api/questions/forecast/",
        {
          method: "POST",
          headers: headers,
          body: JSON.stringify(forecastData)
        }
      );

      if (response.status === 201) {
        console.log("Forecast submitted successfully!");
      } else {
        console.log(`Error: ${response.status}`);
        console.log(await response.json());
      }
      ```

      ```bash cURL theme={null}
      # Note: Full CDF array truncated for readability
      curl -X POST "https://www.metaculus.com/api/questions/forecast/" \
        -H "Authorization: Token your_api_token_here" \
        -H "Content-Type: application/json" \
        -d '[{
          "question": 3530,
          "continuous_cdf": [0.0, 0.00005, 0.0001, ...]
        }]'
      ```
    </CodeGroup>
  </Step>
</Steps>

## Multiple Choice Questions

For multiple choice questions, provide probabilities for each option that sum to 1.0.

<CodeGroup>
  ```python Python theme={null}
  import requests

  API_TOKEN = "your_api_token_here"
  headers = {"Authorization": f"Token {API_TOKEN}"}

  # Submit multiple choice forecast
  forecast_data = [
      {
          "question": 20772,
          "probability_yes_per_category": {
              "Democratic": 0.45,
              "Republican": 0.40,
              "Libertarian": 0.08,
              "Green": 0.05,
              "Other": 0.02
          }
      }
  ]

  response = requests.post(
      "https://www.metaculus.com/api/questions/forecast/",
      headers=headers,
      json=forecast_data
  )

  if response.status_code == 201:
      print("Forecast submitted successfully!")
  ```

  ```javascript JavaScript theme={null}
  const API_TOKEN = "your_api_token_here";
  const headers = {
    "Authorization": `Token ${API_TOKEN}`,
    "Content-Type": "application/json"
  };

  // Submit multiple choice forecast
  const forecastData = [
    {
      question: 20772,
      probability_yes_per_category: {
        "Democratic": 0.45,
        "Republican": 0.40,
        "Libertarian": 0.08,
        "Green": 0.05,
        "Other": 0.02
      }
    }
  ];

  const response = await fetch(
    "https://www.metaculus.com/api/questions/forecast/",
    {
      method: "POST",
      headers: headers,
      body: JSON.stringify(forecastData)
    }
  );

  if (response.status === 201) {
    console.log("Forecast submitted successfully!");
  }
  ```

  ```bash cURL theme={null}
  curl -X POST "https://www.metaculus.com/api/questions/forecast/" \
    -H "Authorization: Token your_api_token_here" \
    -H "Content-Type: application/json" \
    -d '[{
      "question": 20772,
      "probability_yes_per_category": {
        "Democratic": 0.45,
        "Republican": 0.40,
        "Libertarian": 0.08,
        "Green": 0.05,
        "Other": 0.02
      }
    }]'
  ```
</CodeGroup>

<Warning>
  The probabilities must sum to exactly 1.0, or the API will reject your forecast.
</Warning>

## Group of Questions

For posts containing multiple sub-questions, submit forecasts for each one:

<CodeGroup>
  ```python Python theme={null}
  import requests

  API_TOKEN = "your_api_token_here"
  headers = {"Authorization": f"Token {API_TOKEN}"}

  # Submit forecasts for multiple questions in a group
  forecast_data = [
      {"question": 10880, "probability_yes": 0.11},  # 2030
      {"question": 10923, "probability_yes": 0.22},  # 2035
      {"question": 10924, "probability_yes": 0.33}   # 2040
  ]

  response = requests.post(
      "https://www.metaculus.com/api/questions/forecast/",
      headers=headers,
      json=forecast_data
  )

  if response.status_code == 201:
      print("All forecasts submitted successfully!")
  ```

  ```javascript JavaScript theme={null}
  const API_TOKEN = "your_api_token_here";
  const headers = {
    "Authorization": `Token ${API_TOKEN}`,
    "Content-Type": "application/json"
  };

  // Submit forecasts for multiple questions in a group
  const forecastData = [
    {question: 10880, probability_yes: 0.11},  // 2030
    {question: 10923, probability_yes: 0.22},  // 2035
    {question: 10924, probability_yes: 0.33}   // 2040
  ];

  const response = await fetch(
    "https://www.metaculus.com/api/questions/forecast/",
    {
      method: "POST",
      headers: headers,
      body: JSON.stringify(forecastData)
    }
  );

  if (response.status === 201) {
    console.log("All forecasts submitted successfully!");
  }
  ```

  ```bash cURL theme={null}
  curl -X POST "https://www.metaculus.com/api/questions/forecast/" \
    -H "Authorization: Token your_api_token_here" \
    -H "Content-Type: application/json" \
    -d '[
      {"question": 10880, "probability_yes": 0.11},
      {"question": 10923, "probability_yes": 0.22},
      {"question": 10924, "probability_yes": 0.33}
    ]'
  ```
</CodeGroup>

## Withdrawing Forecasts

You can withdraw your current forecast on a question:

<CodeGroup>
  ```python Python theme={null}
  import requests

  API_TOKEN = "your_api_token_here"
  headers = {"Authorization": f"Token {API_TOKEN}"}

  # Withdraw forecast
  withdrawal_data = [
      {"question": 1}
  ]

  response = requests.post(
      "https://www.metaculus.com/api/questions/withdraw/",
      headers=headers,
      json=withdrawal_data
  )

  if response.status_code == 201:
      print("Forecast withdrawn successfully!")
  ```

  ```javascript JavaScript theme={null}
  const API_TOKEN = "your_api_token_here";
  const headers = {
    "Authorization": `Token ${API_TOKEN}`,
    "Content-Type": "application/json"
  };

  // Withdraw forecast
  const withdrawalData = [{question: 1}];

  const response = await fetch(
    "https://www.metaculus.com/api/questions/withdraw/",
    {
      method: "POST",
      headers: headers,
      body: JSON.stringify(withdrawalData)
    }
  );

  if (response.status === 201) {
    console.log("Forecast withdrawn successfully!");
  }
  ```

  ```bash cURL theme={null}
  curl -X POST "https://www.metaculus.com/api/questions/withdraw/" \
    -H "Authorization: Token your_api_token_here" \
    -H "Content-Type: application/json" \
    -d '[{"question": 1}]'
  ```
</CodeGroup>

## Next Steps

* [Learn how to fetch questions](/api/examples/fetching-questions) to find questions to forecast on
* [Read the CDF generation guide](/api/examples/continuous-cdf) for detailed numeric forecast creation
* Explore the [full API reference](/api/overview) for more endpoints


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.