Your first query
A walkthrough. You'll create a ResearchAnything account and an API key, send one research question, read the answer and the sources behind it, and then watch a second run as a stream. By the end you'll have a small script you can build on.
01Create an account
Go to researchanything.ai/signup. Sign up with your email and a password, and enter the six-digit code we email you, or continue with your Essarion ID. If you already use ResearchAnything, sign in instead.
New accounts are on the Free plan, with three research runs a month. Each API call uses one, and this walkthrough makes two calls.
02Create an API key
Open the API Console's keys page at researchanything.ai/console/keys. Choose New key, give it a name you'll recognise later, such as laptop-dev, and choose Create key. The key starts with ra-.
.env file listed in .gitignore.Anyone holding the key can spend your account's research runs. Treat it like a password.
03Set ESSARION_KEY
The examples in these docs read the key from an environment variable named ESSARION_KEY.
export ESSARION_KEY="ra-your-key-here"
04Make the request
Send your question to the query endpoint. The body has one field. The call returns when the run has finished searching, reading and writing, so expect to wait.
curl https://researchanything.ai/api/query \
-H "Authorization: Bearer $ESSARION_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "What is the half-life of caffeine in adults?"}'
05Read the response
The response is a JSON envelope:
{
"request_id": "3f1c9a2e-7b4d-4e8a-9c61-2d5f0b8e4a17",
"status": "ok",
"answer": "In healthy adults, caffeine's half-life is usually reported at around five hours, with wide variation between people [S1][S2]. …",
"sources": [
{ "id": "…", "title": "…", "url": "https://…", "domain": "…", "citations": { "apa": "…" } },
{ "id": "…", "title": "…", "url": "https://…", "domain": "…", "citations": { "apa": "…" } }
],
"usage": { "latency_ms": 94210, "tokens_in": 11, "tokens_out": 612 },
"errors": []
}
statusisokwhen the run completed. If it iserror,answerisnullanderrorssays why, even though the HTTP status is200.answeris Markdown.[S1]points to the first source,[S2]to the second, and so on.sourcesholds the sources the answer was written from, at most five, each with ready-made citations.request_ididentifies this run in the API Console.
Strictly, [Sn] counts only sources without an analysis_error field; see Citation markers. This script handles that and prints the answer followed by its numbered sources:
import os
import requests
resp = requests.post(
"https://researchanything.ai/api/query",
headers={"Authorization": f"Bearer {os.environ['ESSARION_KEY']}"},
json={"query": "What is the half-life of caffeine in adults?"},
timeout=600,
)
data = resp.json()
if resp.status_code != 200 or data.get("status") != "ok":
print("Failed:", data.get("errors") or data.get("detail"))
raise SystemExit(1)
print(data["answer"])
print()
cited = [s for s in data["sources"] if "analysis_error" not in s]
for n, source in enumerate(cited, start=1):
print(f"[S{n}] {source['title']} {source['url']}")
06See what the run did
Open researchanything.ai/console/usage. Your call is listed with its status and latency; open it to see the run's timeline: each phase it went through, the reasoning it wrote as it worked, and the sources it read.
The timeline is in the Console, not behind your API key, so your code can't fetch it with the key. The step-by-step part is kept only for a few hours. If your own product needs that record, stream the run and keep the events, as below. See Run timelines.
07Try streaming
For anything a person watches, stream the run so you can show progress. The streaming endpoint takes the same request and answers with Server-Sent Events.
curl -N https://researchanything.ai/api/query/stream \
-H "Authorization: Bearer $ESSARION_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "Compare lithium-ion and sodium-ion batteries for grid storage."}'
The first events look like this:
event: start
data: {"request_id":"8b2e…","query":"Compare lithium-ion and sodium-ion batteries for grid storage."}
event: step
data: {"phase":"analyzing_query","label":"Analyzing query intent, constraints, and desired output shape",…}
event: reasoning
data: {"step":"analyzing_query","step_id":"analyzing_query","stage":"chunk","chunk":"…"}
event: step
data: {"phase":"searching","label":"Searching web + academic databases...",…}
event: source
data: {"id":"…","title":"…","url":"https://…","stage":"discovered",…}
The stream ends with a final event holding the same envelope as /api/query. Closing the connection early stops the run. For a parser in Node or Python and the pitfalls of relaying a stream, see Streaming with SSE.
08Where to go next
- Show live progress in a UI: Streaming with SSE
- Format and export citations: Working with citations
- Every field and status code: API · Queries
- Put the API behind your own product: Integration patterns