Documentation
Node SDK
Async-first TypeScript SDK for Node 22+.
npm install lamina-sdkNode 22 or newer is required. LAMINA_API_KEY is read from the environment when apiKey is omitted.
Quick start
import { Simi } from "lamina-sdk";
const client = new Simi({ apiKey: "lamina_your_key" });
const video = await client.generate("A narrated lesson about derivatives", {
duration: 1,
});
await video.save("out.mp4");
await client.aclose();duration is in whole minutes, 1 to 5 — the same unit as the HTTP API and the Python SDK.
Stream events
const job = await client.submitAsync("Explain our refund policy", {
duration: 1,
document: "policy.pdf",
});
for await (const event of client.streamEvents(job)) {
if (event.isProgress()) {
console.log(event.payload.phase, event.payload.progress);
} else {
console.log(event.type);
}
}
await client.aclose();The is* guards narrow event.payload to a typed shape. If the stream drops, the SDK reconnects and resumes from the last sequence it delivered, so you will not see an event twice.
Callback style
const job = await client.submitAsync("A narrated lesson about derivatives");
job.onstream((event) => console.log(event.type));
job.oncompletion((video) => console.log(`Ready: ${video.jobId}`));
await job.wait();List, cancel, and play back
const jobs = await client.listJobs({ limit: 10, status: "complete" });
for (const job of jobs) {
console.log(job.jobId, job.status);
}
await client.cancel("job_abc123");
const playback = await client.playback(jobs[0].jobId);
console.log(playback.src, playback.srcAvailable, playback.expiresAt);Retries and errors
Reads are retried automatically on 429 and 5xx with exponential backoff, honouring retry-after. A submit is only retried when you pass an idempotencyKey, so a retry can never create a second video.
import { Simi, SimiRateLimitError } from "lamina-sdk";
const client = new Simi({ maxRetries: 3 });
try {
await client.submitAsync("Explain our refund policy", { idempotencyKey: "req-1" });
} catch (error) {
if (error instanceof SimiRateLimitError) {
console.log(error.status, error.retryAfter, error.requestId);
}
}Every error derives from SimiError: SimiAPIError (carrying status, requestId, and retryAfter), SimiRateLimitError, SimiJobError, SimiStreamError, SimiDownloadError, and SimiCancelledError.
Cancellation and timeouts
const controller = new AbortController();
const video = await client.generate("A narrated lesson about derivatives", {
signal: controller.signal,
timeout: 120,
});Every call accepts an AbortSignal and a per-call timeout in seconds. Closing the client aborts everything still in flight, so a stuck job cannot keep your process alive.