Install
There is deliberately no install command on this page: printing one that resolves to v1 would be worse than printing none. This page updates automatically when publication evidence is recorded.
Authenticate
Construct the client with your API key. It exchanges the key for a short-lived access token automatically. Organization and account arguments are unnecessary; collection methods resolve their workspace on the server. See Authentication for personal-key limits and current access.
Quickstart
// The TypeScript quickstart, compiled against the generated client.
//
// apps/docs/scripts/check-examples.ts typechecks this file against a freshly
// generated SDK, so a contract change that invalidates the documented calls
// fails the docs build instead of shipping a snippet that cannot run.
import { NebulaClient } from "@nebula-ai/sdk";
const nebula = new NebulaClient({
apiKey: process.env.NEBULA_API_KEY!,
});
const workspaceId = process.env.NEBULA_WORKSPACE!;
// 1. Create a collection. `collection_id` is omitted, so the client generates
// a UUID; pass your own to make a retry idempotent.
const collection = await nebula.collections.create({
workspaceId,
body: { name: "Notes" },
});
// 2. Store a memory. Returns an operation, not the finished memory.
const accepted = await nebula.memory.store({
collectionId: collection.collection_id,
body: {
content: { kind: "text", text: "We decided to batch exports nightly." },
metadata: { source: "meeting-notes" },
},
});
// 3. Wait until search can observe it. `search_ready`, not `state`: an
// operation can be succeeded before its content is indexed.
//
// Stop on `cancelled` as well as `failed`. Both are terminal and neither
// ever becomes searchable, so waiting only for `failed` polls forever.
let operation = await nebula.operations.get({
collectionId: collection.collection_id,
operationId: accepted.operation_id,
});
while (
!operation.search_ready
&& operation.state !== "failed"
&& operation.state !== "cancelled"
) {
await new Promise((resolve) => setTimeout(resolve, 500));
operation = await nebula.operations.get({
collectionId: collection.collection_id,
operationId: accepted.operation_id,
});
}
if (!operation.search_ready) {
throw new Error(`operation ${accepted.operation_id} ended ${operation.state}`);
}
// 4. Search.
const results = await nebula.memory.search({
collectionId: collection.collection_id,
body: { query: "how do we handle exports" },
});
for (const hit of results.data) {
console.log(hit.relevance.toFixed(2), hit.summary, `— ${hit.citation.label}`);
}The file above is typechecked against a freshly generated client by
pnpm --dir apps/docs check-examples, so it cannot drift from the contract.
What it covers
The client is generated from the same OpenAPI contract this site documents, so every operation in the API reference is available with the same field names.
Errors surface as typed exceptions carrying the machine-readable code from
error codes; authentication failures carry a
problem code instead.