Lookio Docs
Lookio websiteOpen Lookio
SDKTypeScript SDK

TypeScript SDK

Call Lookio assistants from TypeScript or JavaScript, return answers and citations to your product, stream responses, and continue conversations.

@lookio/sdk is the official TypeScript client for the Lookio API. It has no runtime dependencies and runs on Node 18+, Cloudflare Workers, Deno and Bun, in ESM and CommonJS.

Install and connect

Terminal
npm install @lookio/sdk
TypeScript
import { Lookio } from "@lookio/sdk";

const lookio = new Lookio({ apiKey: process.env.LOOKIO_API_KEY });

Create an API key in Developer tools. For a product that only asks questions, choose Ask questions and limit the key to the assistants it needs. Keep the key on your server. A key in browser code lets visitors use your workspace and spend its credits.

Ask an assistant

TypeScript
const answer = await lookio.assistants.ask("ASSISTANT_ID", {
  question: "How much does the pro plan cost?",
  mode: "flash", // or "eco", "deep"
});

console.log(answer.answer); // Markdown, citations as [1], [2]
for (const c of answer.citations) console.log(c.n, c.title, c.url);
console.log(answer.credit_cost, answer.credits_remaining);

Each answer returned by the model spends the selected mode’s fixed price, even when the resources do not contain an answer. An assistant with no resources is refused before a model call, at no cost. See Credits and plans.

Stream an answer

TypeScript
const stream = lookio.assistants.askStream("ASSISTANT_ID", { question: "Summarise our refund policy." });

for await (const text of stream.textStream()) process.stdout.write(text);

const final = await stream.finalAnswer(); // the same fields as `ask`

The stream is also an async iterable of typed events (status, delta, done, error) and has abort(). Lookio does not automatically retry a stream. If the connection closes after the request reached Lookio, the answer may still finish and spend credits. Check the conversation or usage before asking again. See Streaming answers.

Import a file and wait until it is ready

TypeScript
import { openAsBlob } from "node:fs";

const file = await openAsBlob("./handbook.pdf");
const resource = await lookio.resources.uploadFile(file, "handbook.pdf", { title: "Employee handbook", tags: ["hr"] });
const ready = await lookio.resources.waitUntilReady(resource.id); // throws ResourceFailedError if reading fails

uploadFile takes a Blob, File, ArrayBuffer, Uint8Array or web ReadableStream (with { contentLength }).

Walk every resource

TypeScript
for await (const resource of lookio.resources.iterate({ tags: ["hr"], status: "ready" })) {
  console.log(resource.id, resource.title);
}

Lists return { data, hasMore, nextCursor }; iterate() follows the cursors for you.

Schedule a site

resources.createSite and sites.updateRules accept manual, daily, weekly, monthly, or an interval such as every_3_days, every_2_weeks or every_1_month. Intervals range from 1 to 90 days, 1 to 52 weeks or 1 to 12 months. Recurring schedules require a paid plan.

When you omit schedule on creation, Lookio uses manual on Free and weekly on paid plans. When you omit it from sites.updateRules, Lookio keeps the current schedule.

Keep a conversation, name your users

TypeScript
const first = await lookio.assistants.ask("ASSISTANT_ID", {
  question: "How much does the Pro plan cost?",
  end_user: "user_42", // your own id for the person asking
});
const followUp = await lookio.assistants.ask("ASSISTANT_ID", {
  question: "And for the annual plan?",
  conversationId: first.conversation_id!, // the history is read server-side
  end_user: "user_42",
});

// Forward your user's thumb, then read where the assistant fails.
await lookio.conversations.feedback(first.conversation_id!, first.message_id!, { rating: "down", comment: "Out of date" });
for await (const chat of lookio.logs.conversations.iterate({ rating: "down" })) console.log(chat.title);

store: false keeps nothing. See Conversations and end users, Feedback on answers and Logs.

end_user is an identifier, not proof of identity. Set it on your server from the person who has already signed in to your product. Check that a conversation belongs to that person before continuing it. Do not trust an end_user or conversation_id from browser code without checking it.

Use an assistant in your product

Call the SDK from your backend, such as a Node.js API route or Cloudflare Worker. Return only the fields your interface needs to the browser:

TypeScript
const answer = await lookio.assistants.ask("ASSISTANT_ID", {
  question,
  end_user: authenticatedUser.id,
});

return Response.json({
  answer: answer.answer,
  citations: answer.citations,
  conversation_id: answer.conversation_id,
});

For a follow-up, pass the verified conversation id to assistants.ask. The SDK returns answers and data; it does not render a chat interface. Use the Widget if you want Lookio to provide the chat UI.

Put an assistant on a website

TypeScript
const widget = await lookio.widgets.create({
  assistant_id: "ASSISTANT_ID",
  allowed_domains: ["docs.acme.com"],
  settings: { accent: "#0F766E", sources: "numbered_no_links" },
});
console.log(widget.snippets.bubble); // paste on your site

See Widget.

What is built in

IdempotencyEvery POST except a stream carries an Idempotency-Key, the same on every retry: a retried question is never charged twice. Pass { idempotencyKey } to choose it.
RetriesUp to maxRetries (2) on 429, 408, 5xx and network errors, with backoff and Retry-After. Never on another 4xx; never a PATCH that may have landed.
TimeoutstimeoutMs per client or per call (60 seconds). Pass a signal to cancel.
ErrorsEvery failure is a LookioError with status, code, param, requestId, actionUrl. Subclasses: AuthenticationError, PermissionError, NotFoundError, ConflictError, RateLimitError, InsufficientCreditsError, ConnectionError. Branch on code, never on the message.
TypesGenerated from the OpenAPI document, in the API’s own snake_case.

Methods

NamespaceMethods
account, credits, usageaccount.get(), credits.get(), usage.get()
resourceslist, iterate, get, createText, createUrl, createSite, uploadFile, update, delete, content, reindex, waitUntilReady, pages, iteratePages
sitespreview, pages, iteratePages, updateRules, retryFailed
tagslist, rename, delete
assistantslist, get, create, update, delete, ask, askStream
conversationslist, iterate, get, rename, delete, feedback: your own conversations (an API key’s, with end_user)
logsconversations.list, .iterate, .get, .stats; answers.list, .iterate, .stats; indexing.list, .iterate, .stats; activity.list, .iterate: the workspace’s four logs
widgetslist, get, create, update, duplicate, setImage, clearImage, delete, conversations.list, conversations.iterate, conversations.get
memberslist, updatePermissions
feedbacksend to report a problem with Lookio

lookio.request({ method, path, body }) reaches any endpoint with the same authentication, retries and idempotency.

Use these docs with your AI tools

An AI agent can read this documentation directly. You do not need an account or an API key. Everything here is public and read-only.

Query these docs via MCP

Recommended

Add this server to Claude, Claude Code, Cursor, Mistral, or any tool that supports MCP. Your agent can then search Lookio Docs documentation and read it in full, instead of answering from memory.

https://lookio.app/docs/mcp
  • searchFind the passages that answer a question.
  • fetchRead one page in full, as Markdown.
  • list_pagesSee every page in this documentation.

Query these docs over HTTP

The same tools also work as plain web requests. Use this for scripts, or for any tool that does not support MCP. There is one endpoint per tool. Arguments go in the query string, and the answer comes back as JSON.

https://lookio.app/docs/api/docs/search?query=custom+domain

Read the OpenAPI description. It is built from the same definitions as the tools, so it always matches what the endpoints do.

Read these docs as Markdown

Add .md to any page URL to get its Markdown source. You can also send the headerAccept: text/markdown to the page URL itself.

To read the whole documentation in one file, open llms-full.txt. For a short index of every page, open llms.txt.