DocsGuidesYour first query

Your first query.

A five-minute walkthrough. You'll sign up for an account, generate an API key, run a single research query against the engine, and pull the full timeline of what happened. By the end you'll have a working pattern you can drop straight into your own code.

TipIf you'd rather skim, the entire flow is six lines of curl. Skip to Make the request.

§ 01Sign up at essarion.com

Head to essarion.com and create an account. Email and password is fine; SSO is available on team plans. Once you're in, you'll land on the workspace home — the dashboard with your projects, recent runs, and a sidebar for keys and usage.

You don't need to set anything up in the workspace itself for this walkthrough. We're going to leave the UI almost immediately and drive the engine from a terminal.

§ 02Create an API key

In the dashboard sidebar, open Settings → API keys and click Create key. Give it a label that will mean something to you later — laptop-dev, staging-server, ci-runner. The key is created instantly and looks like this:

esk_live_4f3a2b1c9d8e7f6a5b4c3d2e1f0a9b8c
CautionThe key is shown once. If you close the dialog without copying it, you'll have to revoke it and make a new one. Store it somewhere reasonable — a password manager, a secret in your CI, an .env file that is in your .gitignore.

The key gives the holder full programmatic access to your account at the plan limits you've configured. Treat it like a password.

§ 03Set ESSARION_KEY in your environment

Every example in these docs assumes the key is in an environment variable named ESSARION_KEY. Set it now so the rest of this guide works as-is.

bash
export ESSARION_KEY="esk_live_4f3a2b1c9d8e7f6a5b4c3d2e1f0a9b8c"

For Node and Python work, drop it into a .env file alongside your project and load it with whatever you normally use (dotenv, python-dotenv, your shell's direnv, etc.).

§ 04Make the request

The simplest possible call is a synchronous POST to the query endpoint. The body is a single field — your question — and the response is the final answer plus metadata.

POSThttps://api.essarion.com/api/v1/query
curl
curl https://api.essarion.com/api/v1/query \
  -H "Authorization: Bearer $ESSARION_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query":"What changed in the Inflation Reduction Act in 2024?"}'
node
const res = await fetch("https://api.essarion.com/api/v1/query", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.ESSARION_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    query: "What changed in the Inflation Reduction Act in 2024?",
  }),
});

const data = await res.json();
console.log(data.request_id, data.answer);
python
import os, httpx

r = httpx.post(
    "https://api.essarion.com/api/v1/query",
    headers={"Authorization": f"Bearer {os.environ['ESSARION_KEY']}"},
    json={"query": "What changed in the Inflation Reduction Act in 2024?"},
    timeout=120.0,
)
data = r.json()
print(data["request_id"], data["answer"][:200])
NoteSynchronous queries can take 30 seconds to a few minutes depending on depth. Set a generous client timeout — at least 120 seconds — or move to streaming (covered later).

§ 05Read the response

The response is a JSON envelope with the final answer, the citations the engine used to construct it, and a few pieces of metadata you'll want to hold onto.

json
{
  "request_id": "req_01HXY8K3M4N5P6Q7R8S9T0V1W2",
  "session_id": "ses_01HXY8K3M4N5P6Q7R8S9T0V1W2",
  "status": "completed",
  "answer": "The Inflation Reduction Act saw three significant 2024 amendments...",
  "citations": [
    {
      "id": "cit_01",
      "title": "Treasury Final Rule on §45V Hydrogen Credit",
      "url": "https://home.treasury.gov/...",
      "publisher": "U.S. Department of the Treasury",
      "published_at": "2024-12-15"
    }
  ],
  "usage": {
    "tokens_in": 1842,
    "tokens_out": 1106,
    "cost_usd": 0.0421
  },
  "created_at": "2026-04-30T14:21:08Z"
}

The answer field is plain text with inline citation markers like [1], [2] that index into the citations array. You can render those however you like — as superscripts, footnotes, hover-cards, or strip them entirely.

§ 06Capture the request_id and fetch the timeline

The request_id is the most important field on the response. It uniquely identifies this run forever, and you can use it to fetch the full timeline of what the engine did — every sub-query, every source it considered, every reasoning step.

GEThttps://api.essarion.com/api/v1/runs/{request_id}
curl
curl https://api.essarion.com/api/v1/runs/req_01HXY8K3M4N5P6Q7R8S9T0V1W2 \
  -H "Authorization: Bearer $ESSARION_KEY"
json
{
  "request_id": "req_01HXY8K3M4N5P6Q7R8S9T0V1W2",
  "status": "completed",
  "events": [
    { "t": "2026-04-30T14:21:08.012Z", "type": "start",     "query": "..." },
    { "t": "2026-04-30T14:21:08.430Z", "type": "plan",      "subqueries": 7 },
    { "t": "2026-04-30T14:21:09.118Z", "type": "search",    "engine": "web", "n": 84 },
    { "t": "2026-04-30T14:21:14.901Z", "type": "screen",    "kept": 22, "discarded": 62 },
    { "t": "2026-04-30T14:21:38.244Z", "type": "analyze",   "stage": "deep", "sources": 12 },
    { "t": "2026-04-30T14:22:11.781Z", "type": "synthesize" },
    { "t": "2026-04-30T14:22:14.005Z", "type": "final" }
  ],
  "duration_ms": 65993
}
TipPersist request_id in your own database at submit time, not at completion. If your client disconnects mid-run, you can still recover the result by fetching the timeline later.

§ 07Try streaming

For anything user-facing, you'll want streaming so you can show partial output as the engine works. The streaming endpoint mirrors /query but returns a Server-Sent Events feed.

POSThttps://api.essarion.com/api/v1/query/stream
curl
curl --no-buffer https://api.essarion.com/api/v1/query/stream \
  -H "Authorization: Bearer $ESSARION_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query":"What changed in the Inflation Reduction Act in 2024?"}'

The first few lines you'll see look like this:

sse
event: start
data: {"request_id":"req_01HXY8K3M4N5P6Q7R8S9T0V1W2"}

event: message
data: {"text":"Planning sub-queries..."}

event: sources
data: {"stage":"discovered","count":84}

event: sources
data: {"stage":"screened","count":22}

event: reasoning
data: {"text":"Treasury issued final rules on..."}

event: final
data: {"answer":"...","citations":[...]}

The deeper streaming guide — including a full browser-side parser and reconnection strategy — is in Streaming with SSE.

§ 08Where to go next

You've now run a query, read the response, and pulled the timeline. From here, pick what matches your goal: