Ask vs. Search
Agentic search — POST /v1/insights/ask
Send a research question; our agent decomposes it into sub-queries, runs them against the corpus, and curates the evidence. It resolves sources by name — “what has BG2 said about OpenAI?”, “on Invest Like the Best…” — scoping retrieval to that show (across all of its feeds), and finds the episodes where a topic was actually discussed before reading them.
By default the response is evidence-only — sources with
answer: null, ~10–30s — the natural mode when you’re combining our
evidence with other data in your own generation. Pass "answer": true to
also get a written, cited answer (every [n] maps to a source object); it
adds ~15–25s, so expect ~25–45s end-to-end.
The agent picks its own filters from the question’s wording: name a show or an episode and it scopes to that source, name an audience (“what do investors think…”) and it filters by speaker role, give a window (“since June”) and it dates the search.
Evidence only (default):
Full written answer:
Scoped to a source by name and tracked over time — no ids needed:
Streaming
POST /v1/insights/ask/stream delivers the same over SSE — sub-query
events as retrieval progresses, then answer deltas when the written answer
is on. Events: stage, sub_query, sub_query_result, retrieval_done,
sources, answer_delta, done, ping, error.
Each event is a data: line whose JSON carries a type field — there are
no named SSE event: frames, so parse the JSON rather than using
addEventListener("stage", …). done repeats the complete answer — treat
it as the canonical text; answer_delta events are for display.
Reading the response
Every response carries note_type and note: null when evidence was
found; "source_not_covered" when a named show or episode isn’t in the
corpus (absence means not covered, not that it said nothing); and
"no_evidence" when covered ground simply had nothing on the question.
Branch on note_type — not covered is never a silent blank. On the
stream, the pair rides on the done event. Responses also include
took_ms and a small timing debug object.
Individual search — POST /v1/insights/search
If your platform has its own decomposer and orchestrator, this is your endpoint: deterministic, filterable, fast (~1s filter-only; semantic queries take a few seconds — they include a relevance rerank), and every parameter is a hard guarantee rather than an agent’s judgment call. Your agents compose the sub-queries; you own ranking fusion and synthesis.
Sentiment filtering — three rules
sentimentstogether withtickersmatches as a pair on one mention: “bearish about NVDA”, never bearish-about-something-else while mentioning NVDA.sentimentsalone means “has that sentiment about anything” — a browse of bearish takes, not a claim about a specific company.- Lists combine as any-of. For different stances on different companies —
bullish NVDA or bearish AMD in one call — use
mentionspairs:
Worked examples
Evidence pack — bearish takes on NVDA from professional investors, with verbatim grounding:
Follow one voice — everything a show has said on a topic (idl2iow9 is
The Real Eisman Playbook, resolved via the directory):
Pagination
The response envelope is always {"results": [...], "next_cursor", "pagination_end", "took_ms"} — one page per call, with pagination_end
null while more pages exist. For the next page, send next_cursor back
by itself:
Pages never overlap or reshuffle; cursors expire after ~15 minutes. When
next_cursor is null, pagination_end says why: end_of_results (a
filter-only browse fully paged the matching window) or
ranking_exhausted (a relevance query reached its quality boundary at
~150 results — narrow the query if you need more depth).