Skip to main content

TypeScript SDK

Coming Soon

The official TypeScript SDK is under active development. In the meantime, the REST API works with fetch or any HTTP client.

Planned Installation

npm install @inherent/sdk
# or
pnpm add @inherent/sdk

Using the API Today

No dependencies needed -- the wrapper below uses the built-in fetch API (Node 18+, Bun, Deno, browsers).

Wrapper Client

Drop this into your project as a lightweight SDK until the official one ships.

interface InherentConfig {
apiKey: string;
baseUrl?: string;
}

interface SearchResult {
chunks: Array<{
id: string;
content: string;
score: number;
document_id: string;
metadata: Record<string, unknown>;
}>;
query_id: string;
}

interface Document {
document_id: string;
title: string;
status: string;
created_at: string;
metadata: Record<string, unknown>;
}

interface DocumentUploadResponse {
document_id: string;
status: string;
}

interface DocumentListResponse {
documents: Document[];
total: number;
}

interface DocumentChunk {
id: string;
content: string;
chunk_index: number;
metadata: Record<string, unknown>;
}

interface DocumentContextResponse {
chunks: DocumentChunk[];
document_id: string;
}

class InherentClient {
private apiKey: string;
private baseUrl: string;

constructor(config: InherentConfig) {
this.apiKey = config.apiKey;
this.baseUrl = (config.baseUrl || "https://api.inherent.systems/api/v1").replace(/\/$/, "");
}

private async request<T>(method: string, path: string, body?: unknown): Promise<T> {
const res = await fetch(`${this.baseUrl}${path}`, {
method,
headers: {
"X-API-Key": this.apiKey,
"Content-Type": "application/json",
},
body: body ? JSON.stringify(body) : undefined,
});

if (!res.ok) {
const text = await res.text();
throw new Error(`Inherent API error ${res.status}: ${text}`);
}

return res.json() as Promise<T>;
}

// ── Documents ──────────────────────────────────────────────

async uploadDocument(file: File | Blob, metadata?: Record<string, unknown>): Promise<DocumentUploadResponse> {
const form = new FormData();
form.append("file", file);
if (metadata) {
form.append("metadata", JSON.stringify(metadata));
}

const res = await fetch(`${this.baseUrl}/documents`, {
method: "POST",
headers: { "X-API-Key": this.apiKey },
body: form,
});

if (!res.ok) {
const text = await res.text();
throw new Error(`Inherent API error ${res.status}: ${text}`);
}

return res.json() as Promise<DocumentUploadResponse>;
}

async listDocuments(limit = 20, offset = 0): Promise<DocumentListResponse> {
return this.request("GET", `/documents?limit=${limit}&offset=${offset}`);
}

async getDocument(documentId: string): Promise<Document> {
return this.request("GET", `/documents/${documentId}`);
}

// ── Search ─────────────────────────────────────────────────

async search(query: string, limit = 10): Promise<SearchResult> {
return this.request("POST", "/search", { query, limit });
}

// ── Chunks ─────────────────────────────────────────────────

async getChunks(documentId: string): Promise<DocumentChunk[]> {
return this.request("GET", `/chunks/${documentId}`);
}

async getContext(documentId: string): Promise<DocumentContextResponse> {
return this.request("GET", `/chunks/${documentId}/context`);
}

// ── Health ─────────────────────────────────────────────────

async health(): Promise<{ status: string }> {
return this.request("GET", "/health");
}
}

export { InherentClient, type InherentConfig, type SearchResult, type Document };

Complete Example

Upload a document, wait for processing, search, and retrieve context:

import { InherentClient } from "./inherent-client";
import { readFileSync } from "fs";

const client = new InherentClient({ apiKey: "ink_your_api_key_here" });

async function main() {
// 1. Upload a document
const fileBuffer = readFileSync("./knowledge-base/architecture.md");
const file = new File([fileBuffer], "architecture.md", { type: "text/markdown" });
const doc = await client.uploadDocument(file);
console.log(`Uploaded: ${doc.document_id} — status: ${doc.status}`);

// 2. Wait for ingestion to complete
let status = doc.status;
while (status !== "completed" && status !== "ready") {
if (status === "failed" || status === "error") {
throw new Error(`Ingestion failed for ${doc.document_id}`);
}
await new Promise((r) => setTimeout(r, 2000));
const info = await client.getDocument(doc.document_id);
status = info.status;
console.log(` Processing: ${status}`);
}

// 3. Search across the workspace
const results = await client.search("How does authentication work?", 5);
for (const chunk of results.chunks) {
console.log(`[${chunk.score.toFixed(3)}] ${chunk.content.slice(0, 120)}...`);
}

// 4. Get full context for the top result
const topDocId = results.chunks[0].document_id;
const context = await client.getContext(topDocId);
console.log(`\nContext window (${context.chunks.length} chunks):`);
for (const c of context.chunks) {
console.log(` - ${c.content.slice(0, 80)}...`);
}
}

main().catch(console.error);

Using with Vercel AI SDK

import { generateText } from "ai";
import { openai } from "@ai-sdk/openai";
import { InherentClient } from "./inherent-client";

const inherent = new InherentClient({ apiKey: "ink_your_api_key_here" });

async function answer(question: string): Promise<string> {
// Retrieve context from Inherent
const results = await inherent.search(question, 5);
const context = results.chunks.map((c) => c.content).join("\n\n---\n\n");

// Generate answer with context
const { text } = await generateText({
model: openai("gpt-4o"),
prompt: `Answer based on the following context:\n\n${context}\n\nQuestion: ${question}`,
});

return text;
}

Stay Updated

Star the GitHub repo to get notified when the official SDK launches.