AriseLabsDocsOpen console ↗
Skip to content
API / Research

Research

Research is a deep-research agent over the same corpus Search reads. Three nouns: a session is a conversation; a turn is one question and the background run answering it (minutes, not seconds — it keeps running if you disconnect); a report is the deliverable, an answer with numbered citations, readable forever and free to re-read.

Start a turn

Shell
curl -s -X POST https://api.ariselabs-search-api.com/v1/research/sessions \
  -H "Authorization: Bearer $ARISELABS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query": "TSMC 2025 capex vs guidance"}'
# → 202 {"session_id": "…", "turn_id": "…", "status": "queued", "mode": "new_turn"}

Optional fields: as_of anchors every retrieval to that instant for the whole session; effort sets the effort level supported by your deployment. Posting another question to POST /v1/research/sessions/{id}/turns while a turn is running steers the running turn instead of starting a new one.

Follow progress, read the report

Shell
# live progress (SSE; free): heartbeats every 10s, closed after ≤15 min —
# each frame carries id <session>:<seq>; resume with ?since_seq= to lose nothing
curl -N https://api.ariselabs-search-api.com/v1/research/sessions/$SESSION/events \
  -H "Authorization: Bearer $ARISELABS_API_KEY"

# or just poll the report — while the turn runs this answers
# 409 {"error":{"code":"report_not_ready"}}; 200 = the delivered report
curl -s https://api.ariselabs-search-api.com/v1/research/sessions/$SESSION \
  -H "Authorization: Bearer $ARISELABS_API_KEY"
Python
import httpx, os, time

H = {"Authorization": f"Bearer {os.environ['ARISELABS_API_KEY']}"}
BASE = "https://api.ariselabs-search-api.com"

r = httpx.post(f"{BASE}/v1/research/sessions",
               headers=H, json={"query": "TSMC 2025 capex vs guidance"}).json()
sid = r["session_id"]

while True:  # while the turn runs, the GET answers 409 report_not_ready
    r = httpx.get(f"{BASE}/v1/research/sessions/{sid}", headers=H)
    if r.status_code == 200:
        report = r.json()
        break
    if r.json().get("error", {}).get("code") != "report_not_ready":
        raise SystemExit(r.text)
    time.sleep(10)

print(report["answer"])
for cite in report["citations"]:
    print(f"[{cite['id']}]", cite.get("title"), cite.get("url"))

Disconnecting from the event stream never cancels the run — attaching is a read-only window. POST …/cancel stops the running turn (work already done stays; the session stays usable).

Cost & limits

  • A turn bills by actual token usage, capped at 5,000 credits ($5): the cap is reserved when the turn starts, the difference refunded at delivery — the report's usage.credits is the real bill. Reading, listing, streaming and cancelling are free.
  • 402 quota_exhausted — insufficient credits; add credit in the console. 409 report_not_ready — the turn is still running. concurrency_limit_exceeded — too many turns at once; only a turn finishing or cancel frees a slot.
  • Starting turns is limited to one every 2 s per key — an anti-double-click interval, not a quota. The only volume limit is the wallet.