TypeScript SDK
A small hand-written transport core (auth, retries, rate-limit, typed errors, pagination) over generated types (schema.d.ts, produced from the API’s OpenAPI). The API is the single source of truth — the SDK never hand-encodes field shapes.
Install
npm install @niravi/sdk # 0.2.0
Quickstart
import { connect } from "@niravi/sdk";
const niravi = connect("nv_..."); // dashboard → Settings → Developer
// Semantic search: up to 3 moments per video
const hits = await niravi.search("a person walking at sunset", { limit: 5, momentsPerVideo: 3 });
for (const h of hits) console.log(h.video_id, h.timestamp, h.score, h.raw_score);
// Drill into one video
const video = await niravi.getVideo(hits[0].video_id);
console.log(await video.transcript());
console.log(await video.recallAsk("what happens in this clip?"));
API
connect(apiKey, opts?) → a Niravi handle.
| Method | Description |
|---|---|
niravi.search(query, { limit?, videoId?, engine?, momentsPerVideo?, workspaceIds?, searchOptions?, rerank? }) | Semantic search → hits. engine is "arrow" or "classic" (omit for the workspace default); momentsPerVideo 1 to 10 |
niravi.searchResponse(query, opts?) | The same, resolving to the whole response (results, engine, engine_fallback, …) |
niravi.magicSearch(type, query, { limit?, videoId? }) | Typed search (character/location/music/emotion) |
niravi.chat(message, { videoId?, maxTokens? }) | Conversational Q&A, with citations |
niravi.videos({ limit?, allPages? }) | List videos (paginated) |
niravi.getVideo(id) | → a Video |
niravi.upload(filePath, { filename?, pipeline?, options?, language?, contentType?, timeoutMs? }) | Upload a video, photo or document, Node only (write scope; runs on Arrow). Streams from disk, no timeout unless you pass one |
niravi.deleteVideo(id) | Delete an asset your workspace owns (write scope) |
niravi.downloadNmap(id, destPath?) | The .nmap archive: bytes, or streamed to destPath |
niravi.engines() / niravi.indexOptions() | The search engines; the workspace’s index options |
niravi.workspaces() | The workspaces the key can reach |
niravi.health() / niravi.rateLimit | Health / the last response’s limits: { limit, remaining, reset, limitMinute, limitDay, remainingMinute } (Rate limits) |
Video: transcript(), scenes(), shots(), faces(), characters(), speakers(), sounds(), soundEvents(), audioSegments({ audioType? }), musicTracks(), regions({ page?, timestamp? }), screenplay(), storyboard(), subtitles(format, { raw? }) (raw: true → the SRT/VTT text), frame(timestamp, { jpeg? }) (jpeg: true → the JPEG bytes), nmap(destPath?), recallAsk(question), delete().
const v = await niravi.getVideo(videoId);
const srt = await v.subtitles("srt", { raw: true });
const jpeg = await v.frame(10, { jpeg: true });
await niravi.downloadNmap(videoId, `./${videoId}.nmap`);
await niravi.upload("./episode.mp4", { options: { faces: false }, language: "en" });
Generated types
import type { components } from "@niravi/sdk";
type SearchResponse = components["schemas"]["SearchResponse"];
Auth & options
connect("nv_...", {
baseUrl: "https://api.niravi.io", // default
authScheme: "x-api-key", // default; or "bearer"
workspace: "demo_newsroom", // sent as X-Workspace-Id; omit for the key's home
timeoutMs: 60000, // per request (default); uploads and downloads are not bound by it
maxRetries: 3,
});
A 429 is retried for any call, honouring Retry-After. A 5xx or network error is retried only for idempotent calls (reads, search, chat, recall); an upload is never resent.
Errors
Throws typed errors built from the error envelope: AuthError (401/403), NotFoundError (404), ValidationError (422), RateLimitError (429, carries retryAfter), ServerError (5xx, including 502 chat_unavailable), all subclasses of NiraviError, which carries code, status, requestId and the legacy detail. Other statuses (400, 409 not_ready) throw a plain NiraviError.
import { NotFoundError } from "@niravi/sdk";
try { await niravi.getVideo("nope"); } catch (e) { if (e instanceof NotFoundError) console.log(e.code, e.requestId); }
Pages and People have no SDK helpers yet (their types are in the generated schema.d.ts): call them with fetch (reference). Package: @niravi/sdk · License Apache-2.0.