Documentation Index
Fetch the complete documentation index at: https://docs.vrin.cloud/llms.txt
Use this file to discover all available pages before exploring further.
Insert text
For short content that fits in a JSON body (< ~1MB):
const result = await client.insert({
content: "ACME Corp reported $50M revenue in Q4 2025, up 23% YoY.",
title: "ACME Q4 Earnings",
tags: ["finance", "acme"],
metadata: { source: "internal-slides" },
wait: true, // poll job to completion before returning (default)
});
result.job_id; // "job_abc123"
result.facts_extracted; // 4
InsertOptions
| Field | Type | Default | Description |
|---|
content | string | required | The text to ingest. |
title | string | — | Human-readable title. Shown in source citations. |
tags | string[] | — | Tags for later filtering (future). |
metadata | Record<string, unknown> | — | Free-form metadata stored with the document. |
wait | boolean | true | If true, block until the extraction job completes. |
Upload a file
PDFs, CSVs, markdown, plain text. Images are extracted from PDFs automatically.
import { readFile } from "node:fs/promises";
const buf = await readFile("./earnings.pdf");
const upload = await client.uploadFile({
file: buf,
filename: "earnings.pdf",
saveToMemory: true,
});
upload.upload_id; // "upload_xyz"
upload.status; // "completed" (because wait defaults to true)
const input = document.querySelector<HTMLInputElement>("#file")!;
const blob = input.files![0];
if (blob) {
await client.uploadFile({ file: blob, filename: blob.name });
}
const file = Bun.file("./earnings.pdf");
await client.uploadFile({
file: await file.arrayBuffer() as unknown as Uint8Array,
filename: "earnings.pdf",
});
Supported file types
- PDF (text + tables + images)
- CSV
- Markdown
- Plain text (.txt)
- DOCX
Max file size depends on your plan: free tier is 10MB. See user limits at runtime.
Poll async jobs manually
If you set wait: false and want to poll yourself:
const { job_id } = await client.insert({
content: "...",
wait: false,
});
while (true) {
const status = await client.getJobStatus(job_id!);
if (status.status === "completed") break;
if (status.status === "failed") throw new Error(status.error_details ?? "ingest failed");
await new Promise((r) => setTimeout(r, 2000));
}
Or use the built-in waitForJob:
await client.waitForJob(job_id!, { pollIntervalMs: 1000, timeoutMs: 60_000 });
JobStatus values
status | Meaning |
|---|
pending | Job accepted, not started. |
chunking | Splitting content into chunks. |
extracting | LLM extracting facts + entities. |
storing | Writing to Neptune + OpenSearch. |
completed | Done. Content is now queryable. |
failed | See error_details. |
Upload polling
Uploads have their own status endpoint because the pipeline goes: upload → file processor → fact extraction → ready. wait: true handles polling automatically; to do it manually:
await client.waitForUpload(upload.upload_id);