Queries.
The synchronous query endpoint. Submit a question, get a citation-grade answer back, plus a timeline handle for the persistent run record.
§ 01Endpoint
Authenticates with a Bearer esk_ key (preferred) or the X-API-Key header. See Authentication for both formats.
§ 02Request
The body is a small JSON object. query is the question; metadata is an opaque object echoed back on the timeline for your own bookkeeping.
{
"query": "Compare GDPR and CCPA on data subject deletion rights.",
"metadata": {
"user_id": "u_42",
"trace_id": "abc-def-ghi"
}
}
Parameters
| Param | Type | Required | Description |
|---|---|---|---|
| query | string | yes | The question to research. Plain text. Up to 4,000 characters. Be specific — the engine works best with concrete prompts. |
| metadata | object | no | Free-form JSON. Up to 8 KB. Echoed back on the run timeline. Use it to attach your own user id, trace id, request tags. |
§ 03Response
A 200 response carries the full envelope. request_id is your handle for the run; answer and sources are the synthesized output; usage is the accounting; upstream is engine diagnostics.
| Field | Type | Description |
|---|---|---|
| request_id | string | Stable id for the run. Use to fetch the timeline at /api/v1/runs/{request_id}. |
| status | string | ok on success, error on failure. |
| answer | string | Synthesized answer text. May contain inline citation markers like [1], [2]. |
| sources | array | Source objects — title, url, domain, snippet, relevance, credibility. |
| usage.tokens_in | number | Tokens consumed on input across the full run. |
| usage.tokens_out | number | Tokens generated on output across the full run. |
| usage.latency_ms | number | Wall-clock latency from request receipt to response dispatch. |
| errors | array | { code, message } objects. Empty on success. |
| upstream | object | Engine diagnostics — model, retries, partial failures. |
Status codes
| Code | Meaning |
|---|---|
| 200 | Success. Envelope has status: "ok". |
| 400 | Invalid body — missing query, malformed JSON, oversize input. |
| 401 | Unauthorized — missing, malformed, revoked, or inactive key. |
| 402 | Over quota — plan ceiling reached; upgrade or wait for the next period. |
| 429 | Rate limited — too many requests in a short window. Back off and retry. |
| 502 | Upstream engine error. Transient; retry with backoff. |
| 504 | Upstream timeout. The engine took longer than 180s. Retry, or use the streaming endpoint for longer runs. |
Timeouts
The synchronous endpoint has a 180-second hard timeout. Most queries complete in 10-30 seconds; complex multi-source synthesis can take longer. For runs that may exceed 180s, use streaming instead — the stream timeout is 300s and you see progress as it unfolds.
§ 04Examples
curl
curl https://api.essarion.com/api/v1/query \
-H "Authorization: Bearer $ESSARION_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "Compare GDPR and CCPA on data subject deletion rights.",
"metadata": { "trace_id": "abc-123" }
}'
Node — fetch
async function ask(question) {
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: question,
metadata: { trace_id: crypto.randomUUID() },
}),
});
if (!res.ok) {
const body = await res.json().catch(() => ({}));
throw new Error(`Essarion ${res.status}: ${body?.errors?.[0]?.code ?? "unknown"}`);
}
return res.json();
}
const result = await ask("Compare GDPR and CCPA on data subject deletion rights.");
console.log(result.answer);
Python — httpx
import os, uuid, httpx
def ask(question: str) -> dict:
resp = httpx.post(
"https://api.essarion.com/api/v1/query",
headers={"Authorization": f"Bearer {os.environ['ESSARION_KEY']}"},
json={
"query": question,
"metadata": {"trace_id": str(uuid.uuid4())},
},
timeout=200.0,
)
resp.raise_for_status()
return resp.json()
result = ask("Compare GDPR and CCPA on data subject deletion rights.")
print(result["answer"])
§ 05Example response
An abbreviated 200 response — citation markers in answer, ranked sources with credibility scores, the run accounting, and engine diagnostics.
{
"request_id": "req_01HXYZABC123",
"status": "ok",
"answer": "Both GDPR (Article 17) and CCPA (Section 1798.105) grant a right to deletion, but they differ in scope and exceptions [1][2]. Under GDPR the right applies to any data controller processing personal data of EU residents, while CCPA applies to for-profit businesses meeting specific thresholds operating in California [3]...",
"sources": [
{
"title": "Right to erasure (Article 17)",
"url": "https://gdpr-info.eu/art-17-gdpr/",
"domain": "gdpr-info.eu",
"snippet": "The data subject shall have the right to obtain from the controller the erasure of personal data...",
"relevance": 0.96,
"credibility": 0.92
},
{
"title": "California Consumer Privacy Act — Section 1798.105",
"url": "https://leginfo.legislature.ca.gov/...",
"domain": "leginfo.legislature.ca.gov",
"snippet": "A consumer shall have the right to request that a business delete...",
"relevance": 0.95,
"credibility": 0.95
}
],
"usage": {
"tokens_in": 612,
"tokens_out": 2240,
"latency_ms": 18420
},
"errors": [],
"upstream": {
"model": "essarion-research-1",
"retries": 0,
"sources_discovered": 38,
"sources_analyzed": 12
}
}