curl --request POST \
--url https://api.consensus.app/v1/threads/{thread_id}/interactions \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '
{
"input_message": "<string>",
"mode": "pro",
"filters": {
"year_min": 123,
"year_max": 123,
"month_min": 6,
"month_max": 6,
"study_types": [],
"domain": "<string>",
"country": "<string>",
"human": true,
"controlled": true,
"sample_size_min": 2,
"sjr_min": 2,
"sjr_max": 2,
"citation_min": 123,
"duration_min": 123,
"duration_max": 123,
"exclude_preprints": true,
"open_access": true,
"clinical_guideline": true,
"publisher_name": "<string>",
"journal_name": "<string>"
},
"attachments": {
"paper_ids": [
"<string>"
],
"collection_ids": [
123
]
}
}
'import requests
url = "https://api.consensus.app/v1/threads/{thread_id}/interactions"
payload = {
"input_message": "<string>",
"mode": "pro",
"filters": {
"year_min": 123,
"year_max": 123,
"month_min": 6,
"month_max": 6,
"study_types": [],
"domain": "<string>",
"country": "<string>",
"human": True,
"controlled": True,
"sample_size_min": 2,
"sjr_min": 2,
"sjr_max": 2,
"citation_min": 123,
"duration_min": 123,
"duration_max": 123,
"exclude_preprints": True,
"open_access": True,
"clinical_guideline": True,
"publisher_name": "<string>",
"journal_name": "<string>"
},
"attachments": {
"paper_ids": ["<string>"],
"collection_ids": [123]
}
}
headers = {
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-api-key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
input_message: '<string>',
mode: 'pro',
filters: {
year_min: 123,
year_max: 123,
month_min: 6,
month_max: 6,
study_types: [],
domain: '<string>',
country: '<string>',
human: true,
controlled: true,
sample_size_min: 2,
sjr_min: 2,
sjr_max: 2,
citation_min: 123,
duration_min: 123,
duration_max: 123,
exclude_preprints: true,
open_access: true,
clinical_guideline: true,
publisher_name: '<string>',
journal_name: '<string>'
},
attachments: {paper_ids: ['<string>'], collection_ids: [123]}
})
};
fetch('https://api.consensus.app/v1/threads/{thread_id}/interactions', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.consensus.app/v1/threads/{thread_id}/interactions",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'input_message' => '<string>',
'mode' => 'pro',
'filters' => [
'year_min' => 123,
'year_max' => 123,
'month_min' => 6,
'month_max' => 6,
'study_types' => [
],
'domain' => '<string>',
'country' => '<string>',
'human' => true,
'controlled' => true,
'sample_size_min' => 2,
'sjr_min' => 2,
'sjr_max' => 2,
'citation_min' => 123,
'duration_min' => 123,
'duration_max' => 123,
'exclude_preprints' => true,
'open_access' => true,
'clinical_guideline' => true,
'publisher_name' => '<string>',
'journal_name' => '<string>'
],
'attachments' => [
'paper_ids' => [
'<string>'
],
'collection_ids' => [
123
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.consensus.app/v1/threads/{thread_id}/interactions"
payload := strings.NewReader("{\n \"input_message\": \"<string>\",\n \"mode\": \"pro\",\n \"filters\": {\n \"year_min\": 123,\n \"year_max\": 123,\n \"month_min\": 6,\n \"month_max\": 6,\n \"study_types\": [],\n \"domain\": \"<string>\",\n \"country\": \"<string>\",\n \"human\": true,\n \"controlled\": true,\n \"sample_size_min\": 2,\n \"sjr_min\": 2,\n \"sjr_max\": 2,\n \"citation_min\": 123,\n \"duration_min\": 123,\n \"duration_max\": 123,\n \"exclude_preprints\": true,\n \"open_access\": true,\n \"clinical_guideline\": true,\n \"publisher_name\": \"<string>\",\n \"journal_name\": \"<string>\"\n },\n \"attachments\": {\n \"paper_ids\": [\n \"<string>\"\n ],\n \"collection_ids\": [\n 123\n ]\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.consensus.app/v1/threads/{thread_id}/interactions")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"input_message\": \"<string>\",\n \"mode\": \"pro\",\n \"filters\": {\n \"year_min\": 123,\n \"year_max\": 123,\n \"month_min\": 6,\n \"month_max\": 6,\n \"study_types\": [],\n \"domain\": \"<string>\",\n \"country\": \"<string>\",\n \"human\": true,\n \"controlled\": true,\n \"sample_size_min\": 2,\n \"sjr_min\": 2,\n \"sjr_max\": 2,\n \"citation_min\": 123,\n \"duration_min\": 123,\n \"duration_max\": 123,\n \"exclude_preprints\": true,\n \"open_access\": true,\n \"clinical_guideline\": true,\n \"publisher_name\": \"<string>\",\n \"journal_name\": \"<string>\"\n },\n \"attachments\": {\n \"paper_ids\": [\n \"<string>\"\n ],\n \"collection_ids\": [\n 123\n ]\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.consensus.app/v1/threads/{thread_id}/interactions")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"input_message\": \"<string>\",\n \"mode\": \"pro\",\n \"filters\": {\n \"year_min\": 123,\n \"year_max\": 123,\n \"month_min\": 6,\n \"month_max\": 6,\n \"study_types\": [],\n \"domain\": \"<string>\",\n \"country\": \"<string>\",\n \"human\": true,\n \"controlled\": true,\n \"sample_size_min\": 2,\n \"sjr_min\": 2,\n \"sjr_max\": 2,\n \"citation_min\": 123,\n \"duration_min\": 123,\n \"duration_max\": 123,\n \"exclude_preprints\": true,\n \"open_access\": true,\n \"clinical_guideline\": true,\n \"publisher_name\": \"<string>\",\n \"journal_name\": \"<string>\"\n },\n \"attachments\": {\n \"paper_ids\": [\n \"<string>\"\n ],\n \"collection_ids\": [\n 123\n ]\n }\n}"
response = http.request(request)
puts response.read_body{
"thread_id": "<string>",
"interaction_id": "<string>",
"status": "running",
"mode": "pro",
"url": "<string>",
"poll_after_seconds": 123,
"max_wait_seconds": 123,
"created_at": "2023-11-07T05:31:56Z",
"title": "<string>"
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>"
}
]
}Add a follow-up
Continue the research conversation with full context of the earlier turns. Rate limit: 1 request/second. Refused with 409 while the Thread’s latest interaction is still running, so wait until status is idle or failed first. Returns a new interaction_id immediately; poll GET /v1/threads/{thread_id} until status is idle. A 5xx means the request may or may not have taken effect (no idempotency key yet).
curl --request POST \
--url https://api.consensus.app/v1/threads/{thread_id}/interactions \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '
{
"input_message": "<string>",
"mode": "pro",
"filters": {
"year_min": 123,
"year_max": 123,
"month_min": 6,
"month_max": 6,
"study_types": [],
"domain": "<string>",
"country": "<string>",
"human": true,
"controlled": true,
"sample_size_min": 2,
"sjr_min": 2,
"sjr_max": 2,
"citation_min": 123,
"duration_min": 123,
"duration_max": 123,
"exclude_preprints": true,
"open_access": true,
"clinical_guideline": true,
"publisher_name": "<string>",
"journal_name": "<string>"
},
"attachments": {
"paper_ids": [
"<string>"
],
"collection_ids": [
123
]
}
}
'import requests
url = "https://api.consensus.app/v1/threads/{thread_id}/interactions"
payload = {
"input_message": "<string>",
"mode": "pro",
"filters": {
"year_min": 123,
"year_max": 123,
"month_min": 6,
"month_max": 6,
"study_types": [],
"domain": "<string>",
"country": "<string>",
"human": True,
"controlled": True,
"sample_size_min": 2,
"sjr_min": 2,
"sjr_max": 2,
"citation_min": 123,
"duration_min": 123,
"duration_max": 123,
"exclude_preprints": True,
"open_access": True,
"clinical_guideline": True,
"publisher_name": "<string>",
"journal_name": "<string>"
},
"attachments": {
"paper_ids": ["<string>"],
"collection_ids": [123]
}
}
headers = {
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-api-key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
input_message: '<string>',
mode: 'pro',
filters: {
year_min: 123,
year_max: 123,
month_min: 6,
month_max: 6,
study_types: [],
domain: '<string>',
country: '<string>',
human: true,
controlled: true,
sample_size_min: 2,
sjr_min: 2,
sjr_max: 2,
citation_min: 123,
duration_min: 123,
duration_max: 123,
exclude_preprints: true,
open_access: true,
clinical_guideline: true,
publisher_name: '<string>',
journal_name: '<string>'
},
attachments: {paper_ids: ['<string>'], collection_ids: [123]}
})
};
fetch('https://api.consensus.app/v1/threads/{thread_id}/interactions', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.consensus.app/v1/threads/{thread_id}/interactions",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'input_message' => '<string>',
'mode' => 'pro',
'filters' => [
'year_min' => 123,
'year_max' => 123,
'month_min' => 6,
'month_max' => 6,
'study_types' => [
],
'domain' => '<string>',
'country' => '<string>',
'human' => true,
'controlled' => true,
'sample_size_min' => 2,
'sjr_min' => 2,
'sjr_max' => 2,
'citation_min' => 123,
'duration_min' => 123,
'duration_max' => 123,
'exclude_preprints' => true,
'open_access' => true,
'clinical_guideline' => true,
'publisher_name' => '<string>',
'journal_name' => '<string>'
],
'attachments' => [
'paper_ids' => [
'<string>'
],
'collection_ids' => [
123
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.consensus.app/v1/threads/{thread_id}/interactions"
payload := strings.NewReader("{\n \"input_message\": \"<string>\",\n \"mode\": \"pro\",\n \"filters\": {\n \"year_min\": 123,\n \"year_max\": 123,\n \"month_min\": 6,\n \"month_max\": 6,\n \"study_types\": [],\n \"domain\": \"<string>\",\n \"country\": \"<string>\",\n \"human\": true,\n \"controlled\": true,\n \"sample_size_min\": 2,\n \"sjr_min\": 2,\n \"sjr_max\": 2,\n \"citation_min\": 123,\n \"duration_min\": 123,\n \"duration_max\": 123,\n \"exclude_preprints\": true,\n \"open_access\": true,\n \"clinical_guideline\": true,\n \"publisher_name\": \"<string>\",\n \"journal_name\": \"<string>\"\n },\n \"attachments\": {\n \"paper_ids\": [\n \"<string>\"\n ],\n \"collection_ids\": [\n 123\n ]\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.consensus.app/v1/threads/{thread_id}/interactions")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"input_message\": \"<string>\",\n \"mode\": \"pro\",\n \"filters\": {\n \"year_min\": 123,\n \"year_max\": 123,\n \"month_min\": 6,\n \"month_max\": 6,\n \"study_types\": [],\n \"domain\": \"<string>\",\n \"country\": \"<string>\",\n \"human\": true,\n \"controlled\": true,\n \"sample_size_min\": 2,\n \"sjr_min\": 2,\n \"sjr_max\": 2,\n \"citation_min\": 123,\n \"duration_min\": 123,\n \"duration_max\": 123,\n \"exclude_preprints\": true,\n \"open_access\": true,\n \"clinical_guideline\": true,\n \"publisher_name\": \"<string>\",\n \"journal_name\": \"<string>\"\n },\n \"attachments\": {\n \"paper_ids\": [\n \"<string>\"\n ],\n \"collection_ids\": [\n 123\n ]\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.consensus.app/v1/threads/{thread_id}/interactions")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"input_message\": \"<string>\",\n \"mode\": \"pro\",\n \"filters\": {\n \"year_min\": 123,\n \"year_max\": 123,\n \"month_min\": 6,\n \"month_max\": 6,\n \"study_types\": [],\n \"domain\": \"<string>\",\n \"country\": \"<string>\",\n \"human\": true,\n \"controlled\": true,\n \"sample_size_min\": 2,\n \"sjr_min\": 2,\n \"sjr_max\": 2,\n \"citation_min\": 123,\n \"duration_min\": 123,\n \"duration_max\": 123,\n \"exclude_preprints\": true,\n \"open_access\": true,\n \"clinical_guideline\": true,\n \"publisher_name\": \"<string>\",\n \"journal_name\": \"<string>\"\n },\n \"attachments\": {\n \"paper_ids\": [\n \"<string>\"\n ],\n \"collection_ids\": [\n 123\n ]\n }\n}"
response = http.request(request)
puts response.read_body{
"thread_id": "<string>",
"interaction_id": "<string>",
"status": "running",
"mode": "pro",
"url": "<string>",
"poll_after_seconds": 123,
"max_wait_seconds": 123,
"created_at": "2023-11-07T05:31:56Z",
"title": "<string>"
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>"
}
]
}Authorizations
Path Parameters
Opaque Thread id.
^[A-Za-z0-9_-]+$Body
POST /v1/threads/{thread_id}/interactions body (thread_id is the path).
The follow-up task. Earlier interactions are used as context automatically — don't restate them.
1 - 10000Depth for this follow-up.
pro, deep Global filters applied to every search the agent runs (shared /v1/search vocabulary).
Field set must match the filter fields of
features/quick_search/schema.py:QuickSearchSearchParams (the RFC says the
two surfaces share one filter schema); parity is pinned by
schema_test.py. Values are validated here, not just typed: downstream
parsers silently drop unknown domain/study-type values, and an expensive
agent run must not execute without a restriction the caller asked for.
Show child attributes
Show child attributes
Scope the research to specific papers/collections.
Show child attributes
Show child attributes
Response
Successful Response
POST /v1/threads and POST /v1/threads/{thread_id}/interactions.
Always running on dispatch.
running, idle, failed pro, deep Deep-link to the Thread on consensus.app.
Recommended wait between GET /v1/threads/{thread_id} polls.
Suggested polling ceiling before giving up (~180 pro, ~600 deep).
Auto-generated Thread title.