Welcome to the EvidenceHunt API!
Get started with the EvidenceHunt API in 3 simple steps:
1. Get Your API Key
2. Make Your First Request
curl -X POST https://evidencehunt.com/api/v1/query \
-H "X-API-Key: your_api_key_here" \
-H "Accept: application/vnd.evidencehunt.chat-stream+json" \
-H "Content-Type: application/json" \
-d '{
"question": "What is the efficacy of metformin for type 2 diabetes?",
"sources": ["pubmed"]
}'
3. Process the Streaming Response
The API returns a streaming response with newline-delimited JSON events. Each line is a separate JSON object representing a different event type.
EvidenceHunt API supports two authentication methods:
Include your API key in the request header:
X-API-Key: your_api_key_here
How to get an API key:
For web applications, you can use JWT authentication:
Authorization: Bearer your_jwt_token
Note: Bearer tokens are primarily used by the EvidenceHunt web application. API integrations should use API Key authentication.
Production:
https://evidencehunt.com
Local Development:
http://localhost:8080
Execute a research query against EvidenceHunt's evidence database to get AI-powered answers backed by scientific literature.
Endpoint:
POST /api/v1/query
Required Headers:
X-API-Key: your_api_key_here
Accept: application/vnd.evidencehunt.chat-stream+json
Content-Type: application/json
Request Body:
{
"question": "What is the efficacy of metformin for type 2 diabetes?",
"sources": ["pubmed"],
"chatElaborateMode": false,
"followUp": false,
"userLanguage": "en"
}
| Parameter | Type | Description |
|---|---|---|
question |
string | Your research question (max 1000 tokens) |
| Parameter | Type | Default | Description |
|---|---|---|---|
sources |
array | ["pubmed"] |
Public data sources to search. Only "pubmed" is supported |
customDocuments |
array | [] |
Array of custom organization folder UUIDs to search |
chatElaborateMode |
boolean | false |
Enable for more detailed, comprehensive answers (+1 credit, only when PubMed is included) |
followUp |
boolean | false |
Set to true when asking a follow-up question (+1 credit) |
outputId |
string | - | Required when followUp is true. Use the output_id from previous response |
outputFormat |
string | - | Custom formatting instructions for the answer. By default, responses use Markdown formatting. Use this to change structure, disable Markdown, or customize the output style (no additional credits) |
userLanguage |
string | "en" |
Language code for the answer (see supported languages below) |
The API supports responses in 50+ languages. Use the ISO language code in the userLanguage parameter:
| Code | Language | Code | Language | Code | Language |
|---|---|---|---|---|---|
en |
English | es |
Spanish | fr |
French |
de |
German | zh |
Chinese | ja |
Japanese |
ko |
Korean | ar |
Arabic | ru |
Russian |
pt |
Portuguese | it |
Italian | nl |
Dutch |
pl |
Polish | tr |
Turkish | vi |
Vietnamese |
th |
Thai | sv |
Swedish | hi |
Hindi |
For the complete list of supported languages, see the Language Codes section.
The API returns a streaming response with newline-delimited JSON events. Each line is a separate JSON object with a type field.
X-Credits-Used: 1
X-Credits-Remaining: 99
all_docs - Scientific ArticlesSent first, contains all retrieved scientific articles.
{
"type": "all_docs",
"docs": [
{
"id": "12345",
"title": "Metformin efficacy in Type 2 Diabetes",
"abstract": "This randomized controlled trial demonstrates...",
"authors": ["Smith J", "Johnson A"],
"year": 2023,
"journal": "Diabetes Care",
"doi": "10.1234/dc23-0001"
}
]
}
answer_part - Answer ChunksSent multiple times as the answer is being generated. The text is formatted in Markdown by default.
{
"type": "answer_part",
"text": "Metformin is highly effective ",
"index": 0
}
output_done - Complete AnswerSent at the end with the complete answer and output ID. The answer is formatted in Markdown by default (unless customized with outputFormat).
{
"type": "output_done",
"answer": "Metformin is highly effective for managing type 2 diabetes. Studies show...",
"output_id": "abc-123-xyz"
}
error - Error MessageSent if an error occurs during processing.
{
"type": "error",
"message": "Failed to process query"
}
failed - Query FailedSent if the query completely fails.
{
"type": "failed",
"reason": "Unable to retrieve documents"
}
{"type":"all_docs","docs":[{"id":"12345","title":"Metformin in T2D"}]}
{"type":"answer_part","text":"Metformin is ","index":0}
{"type":"answer_part","text":"highly effective ","index":1}
{"type":"answer_part","text":"for type 2 diabetes.","index":2}
{"type":"output_done","answer":"Metformin is highly effective for type 2 diabetes.","output_id":"abc-123"}
Each API query consumes credits based on the features used:
| Feature | Credits |
|---|---|
| Base query | 1 credit |
Elaborate mode (chatElaborateMode: true) |
+1 credit* |
Follow-up question (followUp: true) |
+1 credit |
| Multiple sources (2+ data sources) | +1 credit |
Custom answer formatting (outputFormat) |
0 credits (free) |
| Maximum per query | 4 credits |
Important Notes:
outputFormat) does not consume additional creditsSimple query: 1 credit
{"question": "What is metformin?", "sources": ["pubmed"]}
Elaborate query: 2 credits
{"question": "What is metformin?", "chatElaborateMode": true}
Follow-up question: 2 credits
{"question": "What are the side effects?", "followUp": true, "outputId": "abc-123"}
Complex query with custom documents: 2 credits
{
"question": "Treatment guidelines?",
"sources": ["pubmed"],
"customDocuments": ["uuid-123"]
}
After each request, check the response headers:
X-Credits-Used: Credits consumed by this requestX-Credits-Remaining: Your remaining credit balanceThe API uses standard HTTP status codes and returns JSON error responses.
| Code | Meaning | Description |
|---|---|---|
200 |
Success | Request successful, streaming response |
400 |
Bad Request | Invalid input or missing required fields |
401 |
Unauthorized | Invalid or missing API key |
402 |
Payment Required | Insufficient credits |
403 |
Forbidden | No access to requested sources |
500 |
Internal Server Error | Server error occurred |
{
"error": "Error message description"
}
Invalid Accept Header:
{
"error": "Provided content type in Accept header is not supported."
}
Missing Required Field:
{
"error": "question is required"
}
Token Limit Exceeded:
{
"error": "Question exceeds maximum token limit of 1000 tokens (current: 1523 tokens)"
}
Invalid Source:
{
"error": "\"sources[0]\" must be [pubmed]"
}
Invalid UUID:
{
"error": "Invalid UUID format: \"not-a-uuid\". Custom document IDs must be valid UUIDs."
}
Invalid Output ID:
{
"error": "Failed to retrieve conversation history. The output_id may be invalid or expired."
}
{
"error": "Invalid API key"
}
{
"error": "Insufficient credits",
"required": 2,
"balance": 0
}
{
"error": "You don't have access to the requested sources"
}
Using Fetch (Modern Node.js 18+):
const API_KEY = 'your_api_key_here';
async function queryEvidenceHunt(question) {
const response = await fetch('https://evidencehunt.com/api/v1/query', {
method: 'POST',
headers: {
'X-API-Key': API_KEY,
'Accept': 'application/vnd.evidencehunt.chat-stream+json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
question: question,
sources: ['pubmed']
})
});
// Check credits
console.log('Credits Used:', response.headers.get('X-Credits-Used'));
console.log('Credits Remaining:', response.headers.get('X-Credits-Remaining'));
// Process streaming response
const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = '';
let fullAnswer = '';
while (true) {
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split('\n');
buffer = lines.pop(); // Keep incomplete line in buffer
for (const line of lines) {
if (line.trim()) {
const event = JSON.parse(line);
switch (event.type) {
case 'all_docs':
console.log(`\nRetrieved ${event.docs.length} documents`);
break;
case 'answer_part':
process.stdout.write(event.text);
fullAnswer += event.text;
break;
case 'output_done':
console.log(`\n\nOutput ID: ${event.output_id}`);
return {
answer: event.answer,
outputId: event.output_id
};
case 'error':
console.error(`\nError: ${event.message}`);
break;
}
}
}
}
}
// Usage
queryEvidenceHunt('What is the efficacy of metformin for type 2 diabetes?')
.then(result => {
console.log('\nQuery completed!');
})
.catch(error => {
console.error('Request failed:', error);
});
Using HTTP Module (Node.js):
const http = require('http');
const https = require('https');
const API_KEY = 'your_api_key_here';
function queryEvidenceHunt(question) {
const data = JSON.stringify({
question: question,
sources: ['pubmed']
});
const options = {
hostname: 'evidencehunt.com',
port: 443,
path: '/api/v1/query',
method: 'POST',
headers: {
'X-API-Key': API_KEY,
'Accept': 'application/vnd.evidencehunt.chat-stream+json',
'Content-Type': 'application/json',
'Content-Length': data.length
}
};
return new Promise((resolve, reject) => {
const req = https.request(options, (res) => {
console.log(`Status: ${res.statusCode}`);
console.log(`Credits Used: ${res.headers['x-credits-used']}`);
console.log(`Credits Remaining: ${res.headers['x-credits-remaining']}`);
let buffer = '';
let outputId = null;
res.on('data', (chunk) => {
buffer += chunk.toString();
const lines = buffer.split('\n');
buffer = lines.pop();
lines.forEach(line => {
if (line.trim()) {
const event = JSON.parse(line);
if (event.type === 'all_docs') {
console.log(`\nRetrieved ${event.docs.length} documents\n`);
} else if (event.type === 'answer_part') {
process.stdout.write(event.text);
} else if (event.type === 'output_done') {
outputId = event.output_id;
}
}
});
});
res.on('end', () => {
console.log(`\n\nOutput ID: ${outputId}`);
resolve(outputId);
});
});
req.on('error', reject);
req.write(data);
req.end();
});
}
// Usage
queryEvidenceHunt('What is the efficacy of metformin for type 2 diabetes?')
.catch(console.error);
Using Requests Library:
import requests
import json
API_KEY = "your_api_key_here"
def query_evidencehunt(question):
"""Query EvidenceHunt API and print streaming response."""
url = "https://evidencehunt.com/api/v1/query"
headers = {
"X-API-Key": API_KEY,
"Accept": "application/vnd.evidencehunt.chat-stream+json",
"Content-Type": "application/json"
}
payload = {
"question": question,
"sources": ["pubmed"],
"chatElaborateMode": True
}
response = requests.post(url, headers=headers, json=payload, stream=True)
# Check credits
print(f"Credits Used: {response.headers.get('X-Credits-Used')}")
print(f"Credits Remaining: {response.headers.get('X-Credits-Remaining')}\n")
if response.status_code != 200:
error_data = response.json()
print(f"Error: {error_data.get('error')}")
return None
# Process streaming response
full_answer = ""
output_id = None
for line in response.iter_lines():
if line:
event = json.loads(line.decode('utf-8'))
if event.get("type") == "all_docs":
docs = event.get("docs", [])
print(f"Retrieved {len(docs)} documents\n")
elif event.get("type") == "answer_part":
text = event.get("text", "")
print(text, end="", flush=True)
full_answer += text
elif event.get("type") == "output_done":
output_id = event.get("output_id")
full_answer = event.get("answer")
print(f"\n\nOutput ID: {output_id}")
elif event.get("type") == "error":
print(f"\nError: {event.get('message')}")
return {
"answer": full_answer,
"output_id": output_id
}
# Usage
if __name__ == "__main__":
result = query_evidencehunt(
"What is the efficacy of metformin for type 2 diabetes?"
)
if result:
print("\n\nQuery completed successfully!")
Follow-up Question Example:
# First query
result1 = query_evidencehunt("What is metformin?")
# Follow-up query using output_id
if result1 and result1.get("output_id"):
url = "https://evidencehunt.com/api/v1/query"
headers = {
"X-API-Key": API_KEY,
"Accept": "application/vnd.evidencehunt.chat-stream+json",
"Content-Type": "application/json"
}
payload = {
"question": "What are the common side effects?",
"sources": ["pubmed"],
"followUp": True,
"outputId": result1["output_id"]
}
response = requests.post(url, headers=headers, json=payload, stream=True)
# Process response...
Basic Query:
curl -X POST https://evidencehunt.com/api/v1/query \
-H "X-API-Key: your_api_key_here" \
-H "Accept: application/vnd.evidencehunt.chat-stream+json" \
-H "Content-Type: application/json" \
-d '{
"question": "What is the efficacy of metformin for type 2 diabetes?",
"sources": ["pubmed"]
}'
Elaborate Mode:
curl -X POST https://evidencehunt.com/api/v1/query \
-H "X-API-Key: your_api_key_here" \
-H "Accept: application/vnd.evidencehunt.chat-stream+json" \
-H "Content-Type: application/json" \
-d '{
"question": "Compare statins vs fibrates for dyslipidemia",
"sources": ["pubmed"],
"chatElaborateMode": true
}'
Include Response Headers:
curl -i -X POST https://evidencehunt.com/api/v1/query \
-H "X-API-Key: your_api_key_here" \
-H "Accept: application/vnd.evidencehunt.chat-stream+json" \
-H "Content-Type: application/json" \
-d '{
"question": "What is metformin?",
"sources": ["pubmed"]
}'
With Type Definitions:
interface QueryRequest {
question: string;
sources?: string[];
customDocuments?: string[];
chatElaborateMode?: boolean;
followUp?: boolean;
outputId?: string;
userLanguage?: string;
}
interface StreamEvent {
type: 'all_docs' | 'answer_part' | 'output_done' | 'error' | 'failed';
docs?: Array<{
id: string;
title: string;
abstract: string;
authors?: string[];
year?: number;
journal?: string;
doi?: string;
}>;
text?: string;
index?: number;
answer?: string;
output_id?: string;
message?: string;
reason?: string;
}
interface QueryResult {
answer: string;
outputId: string;
documents?: any[];
}
class EvidenceHuntAPI {
private apiKey: string;
private baseUrl: string;
constructor(apiKey: string, baseUrl = 'https://evidencehunt.com') {
this.apiKey = apiKey;
this.baseUrl = baseUrl;
}
async query(request: QueryRequest): Promise<QueryResult> {
const response = await fetch(`${this.baseUrl}/api/v1/query`, {
method: 'POST',
headers: {
'X-API-Key': this.apiKey,
'Accept': 'application/vnd.evidencehunt.chat-stream+json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
sources: ['pubmed'],
...request
})
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.error || 'Query failed');
}
// Log credits
console.log('Credits Used:', response.headers.get('X-Credits-Used'));
console.log('Credits Remaining:', response.headers.get('X-Credits-Remaining'));
// Process stream
const reader = response.body!.getReader();
const decoder = new TextDecoder();
let buffer = '';
let result: QueryResult = { answer: '', outputId: '' };
while (true) {
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split('\n');
buffer = lines.pop() || '';
for (const line of lines) {
if (line.trim()) {
const event: StreamEvent = JSON.parse(line);
switch (event.type) {
case 'all_docs':
result.documents = event.docs;
console.log(`\nRetrieved ${event.docs?.length || 0} documents`);
break;
case 'answer_part':
process.stdout.write(event.text || '');
result.answer += event.text || '';
break;
case 'output_done':
result.answer = event.answer || result.answer;
result.outputId = event.output_id || '';
console.log(`\n\nOutput ID: ${result.outputId}`);
break;
case 'error':
throw new Error(event.message || 'Unknown error');
}
}
}
}
return result;
}
async followUp(question: string, outputId: string): Promise<QueryResult> {
return this.query({
question,
followUp: true,
outputId
});
}
}
// Usage
const api = new EvidenceHuntAPI('your_api_key_here');
(async () => {
try {
const result = await api.query({
question: 'What is the efficacy of metformin for type 2 diabetes?',
chatElaborateMode: false
});
console.log('\n\nQuery completed!');
// Ask follow-up
if (result.outputId) {
const followUp = await api.followUp(
'What are the common side effects?',
result.outputId
);
}
} catch (error) {
console.error('Error:', error);
}
})();
Continue a conversation by asking follow-up questions. The AI will maintain context from previous queries.
How it works:
output_id from the output_done eventfollowUp: true and include the outputIdExample:
// First query
const response1 = await fetch('https://evidencehunt.com/api/v1/query', {
method: 'POST',
headers: {
'X-API-Key': API_KEY,
'Accept': 'application/vnd.evidencehunt.chat-stream+json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
question: 'What is metformin?',
sources: ['pubmed']
})
});
// Extract output_id from output_done event
let outputId = '...'; // From output_done event
// Follow-up query
const response2 = await fetch('https://evidencehunt.com/api/v1/query', {
method: 'POST',
headers: {
'X-API-Key': API_KEY,
'Accept': 'application/vnd.evidencehunt.chat-stream+json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
question: 'What are the common side effects?',
sources: ['pubmed'],
followUp: true,
outputId: outputId
})
});
Cost: +1 credit per follow-up question
Search your organization's private documents in addition to public sources like PubMed.
Requirements:
Example:
{
"question": "What are our internal treatment guidelines?",
"sources": ["pubmed"],
"customDocuments": ["550e8400-e29b-41d4-a716-446655440000"]
}
Notes:
Get more detailed, comprehensive answers with additional context and explanations.
Enable elaborate mode:
{
"question": "Compare statins vs fibrates for dyslipidemia",
"sources": ["pubmed"],
"chatElaborateMode": true
}
Benefits:
Cost: +1 credit only when PubMed is included as a source
Important:
Default Behavior: By default, all API responses are formatted in Markdown. This includes headings, lists, tables, bold/italic text, and other Markdown formatting elements to make the content structured and readable.
Customizing the Format: You can customize how the AI formats its response by providing specific formatting instructions using the outputFormat parameter. This feature is free and does not consume additional credits.
Use outputFormat to:
Example - Request a table format:
{
"question": "What are the main side effects of metformin?",
"sources": ["pubmed"],
"outputFormat": "Format the answer as a table with columns: Side Effect, Frequency, Severity"
}
Example - Request bullet points:
{
"question": "What are treatment options for hypertension?",
"sources": ["pubmed"],
"outputFormat": "Translate into plain, patient-friendly language for use in a patient leaflet. Keep answers short, with bulletpoints and in simple educational tone."
}
Example - Request specific structure:
{
"question": "Explain the mechanism of action of aspirin",
"sources": ["pubmed"],
"outputFormat": "Structure the answer with these sections: 1) Mechanism 2) Clinical Effects 3) Contraindications"
}
Example - Disable Markdown formatting:
{
"question": "What is the recommended dosage of aspirin for cardiovascular protection?",
"sources": ["pubmed"],
"outputFormat": "Provide the answer in plain text without any markdown formatting, bold, or italics"
}
Notes:
outputFormat parameter is optional and free to useCost: Free (0 credits)
Get answers in 50+ languages by setting the userLanguage parameter.
Example:
{
"question": "Was ist die Wirksamkeit von Metformin bei Typ-2-Diabetes?",
"sources": ["pubmed"],
"userLanguage": "de"
}
Supported Languages:
| Language | Code | Language | Code | Language | Code |
|---|---|---|---|---|---|
| Albanian | sq |
Arabic | ar |
Belarusian | be |
| Bengali | bn |
Bosnian | bs |
Bulgarian | bg |
| Chinese | zh |
Chinese (Traditional) | zh-TW |
Croatian | hr |
| Czech | cs |
Danish | da |
Dutch | nl |
| English | en |
Esperanto | eo |
Estonian | et |
| Finnish | fi |
French | fr |
Frisian | fy |
| Georgian | ka |
German | de |
Greek | el |
| Hebrew | he |
Hindi | hi |
Hungarian | hu |
| Icelandic | is |
Indonesian | id |
Italian | it |
| Japanese | ja |
Javanese | jw |
Korean | ko |
| Latvian | lv |
Lithuanian | lt |
Macedonian | mk |
| Maltese | mt |
Nepali | ne |
Norwegian | no |
| Persian | fa |
Polish | pl |
Portuguese | pt |
| Romanian | ro |
Russian | ru |
Serbian | sr |
| Slovenian | sl |
Somali | so |
Spanish | es |
| Sundanese | su |
Swahili | sw |
Swedish | sv |
| Thai | th |
Turkish | tr |
Ukrainian | uk |
| Vietnamese | vi |
Current rate limits:
Best Practices:
Need help?
Common Questions:
Q: How do I get more credits? A: Visit your account dashboard to purchase additional credits or upgrade your plan.
Q: Can I use the API for commercial purposes? A: Yes! Please review our terms of service and contact us for enterprise plans.
Q: What happens if I exceed my credit limit? A: The API will return a 402 Payment Required error. Purchase more credits to continue.
Q: How long are output IDs valid for follow-up questions? A: Output IDs are valid for a limited time (typically 24 hours). If expired, you'll receive an error.
Q: Can I search sources other than PubMed? A: Currently, only PubMed is supported as a public source. Contact us about custom data sources for enterprise plans.
Last Updated: November 2025 API Version: 1.0.0