Basic Query
Retrieve a feed of posts (which contain questions):import requests
API_TOKEN = "your_api_token_here"
headers = {"Authorization": f"Token {API_TOKEN}"}
# Get posts feed
response = requests.get(
"https://www.metaculus.com/api/posts/",
headers=headers
)
data = response.json()
print(f"Total posts: {len(data['results'])}")
print(f"Next page: {data['next']}")
for post in data['results']:
print(f"Post {post['id']}: {post['title']}")
if post.get('question'):
print(f" Question type: {post['question']['type']}")
const API_TOKEN = "your_api_token_here";
const headers = { "Authorization": `Token ${API_TOKEN}` };
// Get posts feed
const response = await fetch(
"https://www.metaculus.com/api/posts/",
{ headers }
);
const data = await response.json();
console.log(`Total posts: ${data.results.length}`);
console.log(`Next page: ${data.next}`);
for (const post of data.results) {
console.log(`Post ${post.id}: ${post.title}`);
if (post.question) {
console.log(` Question type: ${post.question.type}`);
}
}
curl -X GET "https://www.metaculus.com/api/posts/" \
-H "Authorization: Token your_api_token_here"
Filtering by Question Type
Filter posts by the type of question they contain:import requests
API_TOKEN = "your_api_token_here"
headers = {"Authorization": f"Token {API_TOKEN}"}
# Get only binary questions
params = {
"forecast_type": ["binary"],
"limit": 20
}
response = requests.get(
"https://www.metaculus.com/api/posts/",
headers=headers,
params=params
)
data = response.json()
for post in data['results']:
question = post.get('question')
if question:
print(f"{question['title']}")
print(f" Status: {question['status']}")
print(f" Open time: {question['open_time']}")
print()
const API_TOKEN = "your_api_token_here";
const headers = { "Authorization": `Token ${API_TOKEN}` };
// Get only binary questions
const params = new URLSearchParams({
forecast_type: "binary",
limit: "20"
});
const response = await fetch(
`https://www.metaculus.com/api/posts/?${params}`,
{ headers }
);
const data = await response.json();
for (const post of data.results) {
const question = post.question;
if (question) {
console.log(question.title);
console.log(` Status: ${question.status}`);
console.log(` Open time: ${question.open_time}`);
console.log();
}
}
curl -X GET "https://www.metaculus.com/api/posts/?forecast_type=binary&limit=20" \
-H "Authorization: Token your_api_token_here"
Available Question Types
binary- Yes/no questionsmultiple_choice- Questions with multiple optionsnumeric- Continuous numeric predictionsdate- Date predictionsconditional- Conditional question pairsgroup_of_questions- Multiple related sub-questions
Filtering by Status
Get questions based on their lifecycle status:import requests
API_TOKEN = "your_api_token_here"
headers = {"Authorization": f"Token {API_TOKEN}"}
# Get only open questions
params = {
"statuses": ["open"],
"forecast_type": ["numeric"],
"limit": 10
}
response = requests.get(
"https://www.metaculus.com/api/posts/",
headers=headers,
params=params
)
data = response.json()
print(f"Found {len(data['results'])} open numeric questions")
for post in data['results']:
question = post.get('question')
if question:
print(f"\nQuestion ID: {question['id']}")
print(f"Title: {question['title']}")
print(f"Close time: {question['scheduled_close_time']}")
print(f"Range: {question['scaling']['range_min']} to {question['scaling']['range_max']}")
const API_TOKEN = "your_api_token_here";
const headers = { "Authorization": `Token ${API_TOKEN}` };
// Get only open questions
const params = new URLSearchParams();
params.append("statuses", "open");
params.append("forecast_type", "numeric");
params.append("limit", "10");
const response = await fetch(
`https://www.metaculus.com/api/posts/?${params}`,
{ headers }
);
const data = await response.json();
console.log(`Found ${data.results.length} open numeric questions`);
for (const post of data.results) {
const question = post.question;
if (question) {
console.log(`\nQuestion ID: ${question.id}`);
console.log(`Title: ${question.title}`);
console.log(`Close time: ${question.scheduled_close_time}`);
console.log(`Range: ${question.scaling.range_min} to ${question.scaling.range_max}`);
}
}
curl -X GET "https://www.metaculus.com/api/posts/?statuses=open&forecast_type=numeric&limit=10" \
-H "Authorization: Token your_api_token_here"
Available Statuses
upcoming- Not yet open for forecastingopen- Currently accepting forecastsclosed- No longer accepting forecastsresolved- Question has been resolved
Filtering by Tournament
Get questions from specific tournaments or projects:import requests
API_TOKEN = "your_api_token_here"
headers = {"Authorization": f"Token {API_TOKEN}"}
# Get questions from specific tournaments
params = {
"tournaments": ["ai-forecasting", "metaculus-cup"],
"statuses": ["open"],
"limit": 20
}
response = requests.get(
"https://www.metaculus.com/api/posts/",
headers=headers,
params=params
)
data = response.json()
for post in data['results']:
print(f"Post: {post['title']}")
# Show which tournaments this post belongs to
if post.get('projects', {}).get('tournament'):
tournaments = [t['name'] for t in post['projects']['tournament']]
print(f" Tournaments: {', '.join(tournaments)}")
print()
const API_TOKEN = "your_api_token_here";
const headers = { "Authorization": `Token ${API_TOKEN}` };
// Get questions from specific tournaments
const params = new URLSearchParams();
params.append("tournaments", "ai-forecasting");
params.append("tournaments", "metaculus-cup");
params.append("statuses", "open");
params.append("limit", "20");
const response = await fetch(
`https://www.metaculus.com/api/posts/?${params}`,
{ headers }
);
const data = await response.json();
for (const post of data.results) {
console.log(`Post: ${post.title}`);
// Show which tournaments this post belongs to
if (post.projects?.tournament) {
const tournaments = post.projects.tournament.map(t => t.name);
console.log(` Tournaments: ${tournaments.join(", ")}`);
}
console.log();
}
curl -X GET "https://www.metaculus.com/api/posts/?tournaments=ai-forecasting&tournaments=metaculus-cup&statuses=open&limit=20" \
-H "Authorization: Token your_api_token_here"
Filtering by Category
Filter questions by topic categories:import requests
API_TOKEN = "your_api_token_here"
headers = {"Authorization": f"Token {API_TOKEN}"}
# Get questions from specific categories
params = {
"categories": ["nuclear", "health-pandemics"],
"statuses": ["open"],
"limit": 15
}
response = requests.get(
"https://www.metaculus.com/api/posts/",
headers=headers,
params=params
)
data = response.json()
for post in data['results']:
print(f"\n{post['title']}")
if post.get('projects', {}).get('category'):
categories = [c['name'] for c in post['projects']['category']]
print(f"Categories: {', '.join(categories)}")
const API_TOKEN = "your_api_token_here";
const headers = { "Authorization": `Token ${API_TOKEN}` };
// Get questions from specific categories
const params = new URLSearchParams();
params.append("categories", "nuclear");
params.append("categories", "health-pandemics");
params.append("statuses", "open");
params.append("limit", "15");
const response = await fetch(
`https://www.metaculus.com/api/posts/?${params}`,
{ headers }
);
const data = await response.json();
for (const post of data.results) {
console.log(`\n${post.title}`);
if (post.projects?.category) {
const categories = post.projects.category.map(c => c.name);
console.log(`Categories: ${categories.join(", ")}`);
}
}
curl -X GET "https://www.metaculus.com/api/posts/?categories=nuclear&categories=health-pandemics&statuses=open&limit=15" \
-H "Authorization: Token your_api_token_here"
Filtering by Date Range
Get questions that opened, close, or resolve within specific date ranges:import requests
from datetime import datetime, timedelta
API_TOKEN = "your_api_token_here"
headers = {"Authorization": f"Token {API_TOKEN}"}
# Get questions that opened in the last 7 days
week_ago = (datetime.now() - timedelta(days=7)).isoformat()
params = {
"open_time__gte": week_ago,
"statuses": ["open"],
"limit": 20,
"order_by": "-open_time" # Most recent first
}
response = requests.get(
"https://www.metaculus.com/api/posts/",
headers=headers,
params=params
)
data = response.json()
print(f"Found {len(data['results'])} questions opened in the last week\n")
for post in data['results']:
question = post.get('question')
if question:
print(f"{question['title']}")
print(f" Opened: {question['open_time']}")
print(f" Type: {question['type']}")
print()
const API_TOKEN = "your_api_token_here";
const headers = { "Authorization": `Token ${API_TOKEN}` };
// Get questions that opened in the last 7 days
const weekAgo = new Date();
weekAgo.setDate(weekAgo.getDate() - 7);
const params = new URLSearchParams({
open_time__gte: weekAgo.toISOString(),
statuses: "open",
limit: "20",
order_by: "-open_time" // Most recent first
});
const response = await fetch(
`https://www.metaculus.com/api/posts/?${params}`,
{ headers }
);
const data = await response.json();
console.log(`Found ${data.results.length} questions opened in the last week\n`);
for (const post of data.results) {
const question = post.question;
if (question) {
console.log(question.title);
console.log(` Opened: ${question.open_time}`);
console.log(` Type: ${question.type}`);
console.log();
}
}
curl -X GET "https://www.metaculus.com/api/posts/?open_time__gte=2024-01-01&statuses=open&limit=20&order_by=-open_time" \
-H "Authorization: Token your_api_token_here"
Available Date Filters
Each filter supports these operators:__gt- Greater than__gte- Greater than or equal to__lt- Less than__lte- Less than or equal to
open_time- When the question opened for forecastingpublished_at- When the post was publishedscheduled_resolve_time- When the question is scheduled to resolve
Pagination
Handle large result sets with pagination:import requests
API_TOKEN = "your_api_token_here"
headers = {"Authorization": f"Token {API_TOKEN}"}
def fetch_all_pages(initial_url, max_pages=5):
"""Fetch multiple pages of results"""
all_posts = []
url = initial_url
page = 0
while url and page < max_pages:
response = requests.get(url, headers=headers)
data = response.json()
all_posts.extend(data['results'])
url = data.get('next') # URL for next page
page += 1
print(f"Fetched page {page}, total posts: {len(all_posts)}")
return all_posts
# Fetch first 5 pages of binary questions
params = {
"forecast_type": ["binary"],
"statuses": ["open"],
"limit": 20,
"offset": 0
}
base_url = "https://www.metaculus.com/api/posts/"
first_url = f"{base_url}?" + "&".join([f"{k}={v}" for k, v in params.items()])
posts = fetch_all_pages(first_url)
print(f"\nTotal posts fetched: {len(posts)}")
const API_TOKEN = "your_api_token_here";
const headers = { "Authorization": `Token ${API_TOKEN}` };
async function fetchAllPages(initialUrl, maxPages = 5) {
/**Fetch multiple pages of results */
const allPosts = [];
let url = initialUrl;
let page = 0;
while (url && page < maxPages) {
const response = await fetch(url, { headers });
const data = await response.json();
allPosts.push(...data.results);
url = data.next; // URL for next page
page++;
console.log(`Fetched page ${page}, total posts: ${allPosts.length}`);
}
return allPosts;
}
// Fetch first 5 pages of binary questions
const params = new URLSearchParams({
forecast_type: "binary",
statuses: "open",
limit: "20",
offset: "0"
});
const url = `https://www.metaculus.com/api/posts/?${params}`;
const posts = await fetchAllPages(url);
console.log(`\nTotal posts fetched: ${posts.length}`);
# Page 1
curl -X GET "https://www.metaculus.com/api/posts/?forecast_type=binary&statuses=open&limit=20&offset=0" \
-H "Authorization: Token your_api_token_here"
# Page 2
curl -X GET "https://www.metaculus.com/api/posts/?forecast_type=binary&statuses=open&limit=20&offset=20" \
-H "Authorization: Token your_api_token_here"
Sorting Results
Order results by different criteria:import requests
API_TOKEN = "your_api_token_here"
headers = {"Authorization": f"Token {API_TOKEN}"}
# Get most commented questions
params = {
"statuses": ["open"],
"order_by": "-comment_count", # Prefix with - for descending
"limit": 10
}
response = requests.get(
"https://www.metaculus.com/api/posts/",
headers=headers,
params=params
)
data = response.json()
print("Most discussed questions:\n")
for post in data['results']:
print(f"{post['title']}")
print(f" Comments: {post['comment_count']}")
print(f" Forecasters: {post['nr_forecasters']}")
print()
const API_TOKEN = "your_api_token_here";
const headers = { "Authorization": `Token ${API_TOKEN}` };
// Get most commented questions
const params = new URLSearchParams({
statuses: "open",
order_by: "-comment_count", // Prefix with - for descending
limit: "10"
});
const response = await fetch(
`https://www.metaculus.com/api/posts/?${params}`,
{ headers }
);
const data = await response.json();
console.log("Most discussed questions:\n");
for (const post of data.results) {
console.log(post.title);
console.log(` Comments: ${post.comment_count}`);
console.log(` Forecasters: ${post.nr_forecasters}`);
console.log();
}
curl -X GET "https://www.metaculus.com/api/posts/?statuses=open&order_by=-comment_count&limit=10" \
-H "Authorization: Token your_api_token_here"
Available Sort Options
published_at- Publication dateopen_time- When question openedvote_score- Community votescomment_count- Number of commentsforecasts_count- Number of forecastsscheduled_close_time- Close datescheduled_resolve_time- Resolution datehotness- Composite popularity scoreweekly_movement- Recent forecast changesdivergence- Disagreement among forecasters
- for descending order (e.g., -published_at).
Getting a Single Post
Retrieve detailed information about a specific post:import requests
API_TOKEN = "your_api_token_here"
headers = {"Authorization": f"Token {API_TOKEN}"}
# Get specific post by ID
post_id = 3530
response = requests.get(
f"https://www.metaculus.com/api/posts/{post_id}/",
headers=headers
)
post = response.json()
print(f"Title: {post['title']}")
print(f"Status: {post['status']}")
print(f"Forecasters: {post['nr_forecasters']}")
print(f"Comments: {post['comment_count']}")
if post.get('question'):
question = post['question']
print(f"\nQuestion Details:")
print(f" Type: {question['type']}")
print(f" ID: {question['id']}")
print(f" Open: {question['open_time']}")
print(f" Close: {question['scheduled_close_time']}")
if question['type'] in ['numeric', 'date']:
print(f" Range: {question['scaling']['range_min']} to {question['scaling']['range_max']}")
print(f" Open bounds: lower={question['open_lower_bound']}, upper={question['open_upper_bound']}")
const API_TOKEN = "your_api_token_here";
const headers = { "Authorization": `Token ${API_TOKEN}` };
// Get specific post by ID
const postId = 3530;
const response = await fetch(
`https://www.metaculus.com/api/posts/${postId}/`,
{ headers }
);
const post = await response.json();
console.log(`Title: ${post.title}`);
console.log(`Status: ${post.status}`);
console.log(`Forecasters: ${post.nr_forecasters}`);
console.log(`Comments: ${post.comment_count}`);
if (post.question) {
const question = post.question;
console.log(`\nQuestion Details:`);
console.log(` Type: ${question.type}`);
console.log(` ID: ${question.id}`);
console.log(` Open: ${question.open_time}`);
console.log(` Close: ${question.scheduled_close_time}`);
if (['numeric', 'date'].includes(question.type)) {
console.log(` Range: ${question.scaling.range_min} to ${question.scaling.range_max}`);
console.log(` Open bounds: lower=${question.open_lower_bound}, upper=${question.open_upper_bound}`);
}
}
curl -X GET "https://www.metaculus.com/api/posts/3530/" \
-H "Authorization: Token your_api_token_here"
