Introduction
A TypeScript SDK for the Sinequa REST API — authentication, search, aggregations, preview — with no framework and no runtime dependencies.
@sinequa/atomic calls the Sinequa REST API from TypeScript. It handles authentication for you, exposes every
endpoint as a typed function, and describes the data that comes back — so you write a search interface instead
of a HTTP client.
It is headless. There are no components, no styles, no state management and no framework: the library returns data and leaves the rendering to you. That is what makes it usable from plain TypeScript, Angular, React or a SharePoint web part alike.
What it does
Authenticates
Username and password, Windows SSO, OAuth, SAML, or a server-to-server token — resolved from the server's own configuration, with session recovery on expiry.
Searches
Full text, filters, facets, tabs, sorting, autocomplete, and the neural-search extras: answers, passages, spelling correction.
Reads documents
Document preview with highlights, text chunks for RAG, similar documents, labels.
Carries the user
Who is signed in, their settings and profile, impersonation, and searching the directory for principals.
What it is not
- Not a UI library. No components, no styles.
@sinequa/atomic-angularadds Angular bindings on top of it, and the components themselves belong to the layer above that. - Not a query language. Filters are typed objects, not strings you assemble.
- Not opinionated about state. It returns promises; where the result lives is your decision.
A first look
Enough to run a search, end to end. There is nothing else to set up on the client side — no interceptor to register, no store to configure.
import { createAtomicClient } from "@sinequa/atomic";
const client = createAtomicClient({
app: "<your-app>",
backendUrl: "https://<your-sinequa-server>",
});
// Reads the server's configuration, then signs in the way that server expects.
await client.initializeConfig();
await client.auth.login();
const result = await client.api.query.search({
name: "<your-query>",
text: "quarterly report",
pageSize: 10,
});
console.log(`${result.rowCount} document(s)`);
for (const record of result.records) {
console.log(record.title, record.modified);
}import { Injectable, inject, signal } from "@angular/core";
import { type AtomicClient, createAtomicClient } from "@sinequa/atomic";
import type { Result } from "@sinequa/atomic";
@Injectable({ providedIn: "root" })
export class SearchService {
private readonly client: AtomicClient = createAtomicClient({
app: "<your-app>",
backendUrl: "https://<your-sinequa-server>",
});
readonly result = signal<Result | undefined>(undefined);
async start() {
await this.client.initializeConfig();
await this.client.auth.login();
}
async search(text: string) {
this.result.set(
await this.client.api.query.search({ name: "<your-query>", text, pageSize: 10 }),
);
}
}import { createAtomicClient } from "@sinequa/atomic";
export const sinequa = createAtomicClient({
app: "<your-app>",
backendUrl: "https://<your-sinequa-server>",
});
/** Awaited by anything that queries, so components share one sign-in. */
export const ready = (async () => {
await sinequa.initializeConfig();
await sinequa.auth.login();
})();
export async function search(text: string) {
await ready;
return sinequa.api.query.search({ name: "<your-query>", text, pageSize: 10 });
}New to Sinequa?
Two things in that snippet come from the server, not from this library: the app, and the query's name
— which identifies a query web service, not the search text. Both are things an administrator configured.
Sinequa in 5 minutes explains them, and it is the shortest path to
understanding every example that follows.
Where to go next
Sinequa in 5 minutes
The backend, for developers who have never seen it. Start here.
Install
Package, entry points, module formats, and the SharePoint subpath.
Your first search
A working search, step by step, in your language of choice.
Core concepts
The client, the configuration, and the two types you will handle constantly.