Skip to content

TypeScript SDK

The same API surface as the Python SDK, in TypeScript. ESM, no runtime dependencies, typed inputs and typed errors.

Install

Not on npm yet — install from the repository

The Python SDK is on PyPI; this one is not yet on the npm registry, so there is no npm install @lithora/sdk that works today. Build it from the repository as below. The package name and the import path are already @lithora/sdk, so nothing in the code samples on this page changes when it is published.
Install the SDK
git clone https://github.com/AADI0009/SaaS-App.git
cd SaaS-App/sdk/typescript && npm install && npm run build

# then, from your own project:
npm install /absolute/path/to/SaaS-App/sdk/typescript

Requires Node 18 or newer — the client uses the platform fetch and AbortSignal, so it has no runtime dependencies at all. It is published as ESM.

Quickstart

Mint a personal access token at Settings → API Tokens, export it as LITHORA_TOKEN, and go.

First script
import { Lithora } from "@lithora/sdk";

const client = new Lithora({ token: process.env.LITHORA_TOKEN });

const me = await client.auth.me();
console.log(me.email);

const tasks = await client.tasks.list("8f1c0c2e-4a2d-4f5b-9c31-6b2a7e0d4411");
console.log(`${tasks.length} tasks`);

Constructing the client

new Lithora(...)
const client = new Lithora({
  baseUrl: "https://api.lithora.app",   // default; http://localhost:8000 for local dev
  token: process.env.LITHORA_TOKEN,     // a lth_pat_… token, or a login JWT
  timeout: 30_000,                      // milliseconds, per request
});

Pass the bare host — the client appends the /api prefix itself. Note that timeouthere is in MILLISECONDS, where the Python SDK’s is in seconds; each follows the convention of its own ecosystem.

Filtering happens on the server

A list call returns a page, not the whole set. Filtering the array it gives you back therefore answers a different question — the matches within one page — and says nothing about what was left out. Pass the filters instead; every one below is a parameter the endpoint declares.

Server-side filters
// Filters are applied by the SERVER, not after the fact.
const done = await client.tasks.list(projectId, { status: "done", limit: 20 });

const children = await client.workItems.list({
  types: ["task", "note"],   // array is joined for you
  parentId: "wi_1c2f…",
  limit: 50,
});

Driving the agent

The agent proposes; you dispose. A chat response with requires_confirmation means nothing has been written — the plan is staged and waiting.

Propose, review, apply
const session = await client.ai.createSession("Triage");
const reply = await client.ai.chat(session.session_id, "Close the stale bugs in Billing");

if (reply.requires_confirmation) {
  // NOTHING has been written yet. reply.action_plan describes what would be.
  await client.ai.confirmAgentAction(session.session_id, reply.action_plan.action_id, true);
}

// Autonomous runs (overnight triage, CI-failure triage) stage plans the same way:
const pending = await client.ai.listPendingActions();

confirmAction() is the deprecated gate

Use confirmAgentAction(), which posts to /api/ai-workspace/agent/confirm. The similarly named confirmAction() targets the legacy intent-parser endpoint. For a long time it was the only confirm this SDK exposed, so code written against older versions may be approving through a path the agent does not stage plans against — worth checking.

Errors

The hierarchy mirrors the Python SDK’s: LithoraError LithoraApiError LithoraAuthError (401), plus LithoraAuthChallengeError for an incomplete login and LithoraTimeoutError for a request that ran out of time.

Handling failures
import {
  LithoraApiError,
  LithoraAuthError,
  LithoraTimeoutError,
} from "@lithora/sdk";

try {
  await client.tasks.create({ title: "Ship it", project_id: projectId });
} catch (err) {
  if (err instanceof LithoraAuthError) {
    // 401 — token missing, expired or revoked
  } else if (err instanceof LithoraApiError && err.status === 422) {
    console.error(err.detail);
  } else if (err instanceof LithoraTimeoutError) {
    // the request exceeded the client timeout
  } else {
    throw err;
  }
}

Resource namespaces

NamespaceMethods
client.authlogin(), me()
client.tokenscreate(), list(), revoke()
client.teamscreate(), list(), get(), members()
client.projectscreate(), list(), get(), update(), patch(), delete()
client.taskscreate(), list(), my(), get(), update(), setStatus(), delete(), bulkCreate(), setGithubRepo(), pushToGithub()
client.workItemslist(), get(), create(), update(), delete(), createRelation(), relations(), children(), parents(), deleteRelation(), cycleTime(), graph(), prStatus(), resolveRef()
client.automationslist(), create(), get(), toggle(), execute(), runs(), runStatus(), export(), versions(), rollback(), templates()
client.githubstatus(), repos(), connectUrl()
client.searchquery(), recent(), suggestions()
client.aicreateSession(), listSessions(), getSession(), chat(), linkItem(), search(), confirmAgentAction(), listPendingActions()
client.runnerscreate(), list(), revoke(), updateManifest(), dispatch(), jobs(), audit()
client.sprintslist(), create(), plan(), velocity(), get(), update(), close(), summary()
client.webhookslist(), create(), eventTypes(), get(), update(), delete(), logs(), clearLogs(), stats(), regenerateSecret(), test()
client.datafields(), export_(), importTasks(), importEntity()

This table and the Python SDK’s are kept in step by a test, not by discipline: CI compares the (verb, path) sets of both SDKs’ source and fails when TypeScript is missing an endpoint Python exposes. That check exists because the two had drifted by 26 endpoints before anyone noticed.

There is no auth.register() in either SDK — the route it called was removed from the API for an account-takeover defect. Accounts are created only through the email-OTP signup flow in the web app.