Recall & Chat
Go beyond retrieval — ask questions and get grounded answers.
Per-video recall
POST /api/v1/recall/{video_id}/ask answers a question using only that video’s transcript, scenes, faces, and sounds — with the evidence it used.
curl https://api.niravi.io/api/v1/recall/$VIDEO_ID/ask \
-H "X-API-Key: $NIRAVI_API_KEY" -H "Content-Type: application/json" \
-d '{"query": "what does the host say about pricing?"}'
import requests # the Python SDK is not on PyPI yet: plain HTTP works
BASE = "https://api.niravi.io/api/v1"
H = {"X-API-Key": "nv_..."}
r = requests.post(f"{BASE}/recall/{video_id}/ask", headers=H,
json={"query": "what does the host say about pricing?"})
data = r.json()["data"]
print(data["answer"])
for c in data["citations"]: # what the answer rests on
print(c["video_id"], c["timestamp"], c["text"])
const video = await niravi.getVideo(videoId);
console.log(await video.recallAsk("what does the host say about pricing?"));
The answer is grounded in what your workspace’s engine indexed (Arrow or classic), and the response says what it rests on, so you can cite or deep-link back into the video:
{ "success": true, "data": {
"answer": "The investigation is about …",
"citations": [ { "video_id": "98dbb102b4a541ec", "timestamp": 20.0, "text": "In a Tampa TV news studio, …",
"snippet": "…", "scene_id": null, "source_tool": "find_videos" } ],
"source_frames": [ /* search hits it used, when any */ ]
} }
A citation’s timestamp is null when the answer drew on the video as a whole (its summary) rather than one moment.
No empty answers. If an answer cannot be composed (the language model is unavailable or returns nothing), the call fails with 502 and error.code chat_unavailable: retry it. A 200 always carries an answer.
Chat over the corpus
POST /api/v1/chat is a conversational query over the whole workspace (or a subset of videos). It retrieves relevant moments with your workspace’s engine and composes an answer, with the same citations and the same 502 chat_unavailable rule as recall.
curl https://api.niravi.io/api/v1/chat \
-H "X-API-Key: $NIRAVI_API_KEY" -H "Content-Type: application/json" \
-d '{"query": "summarize every mention of the product roadmap"}'
| Field | Type | Notes |
|---|---|---|
query | string | required — your message |
video_ids | string[] | restrict the answer to these videos |
max_tokens | int | cap the response length |
r = requests.post(f"{BASE}/chat", headers=H, json={"query": "summarize every mention of the roadmap"})
print(r.json()["data"]["answer"], r.json()["data"]["citations"])
r = requests.post(f"{BASE}/chat", headers=H, json={"query": "what happens here?", "video_ids": [video_id]})
await niravi.chat("summarize every mention of the roadmap");
await niravi.chat("what happens here?", { videoId });
The science behind this → how Niravi reads a video once, deeply — and grounds answers in what it found — is written up in the Engineering Notes at blog.niravi.io/blog.