Skip to main content
The @signa-so/sdk package is a typed, ergonomic client for the Signa API: full types for every endpoint and response, automatic pagination, built-in retries, and typed error classes.
The SDK is designed for server-side use. A Signa API key grants full access to your org’s data; putting one in browser code exposes it to every visitor. Proxy requests through your own backend instead.

Install

Requires Node.js 18+ or Bun 1.0+. TypeScript 5.0+ is recommended but not required.

Configure

If you omit api_key, the client reads SIGNA_API_KEY from the environment:

Resources

The client organizes the API into resource namespaces. The main ones:

Search and list trademarks

search() takes the POST body: q, similarity, structured filters under filters, exclusions under exclude, and options for aggregations, totals, and partial results:
relevance_score orders the results and is not a likelihood of confusion. match.tier and match.via say how close the hit is and which channels found it. See Response. list() takes the flat GET keys. Filters are top-level params, not nested:

Presets

Presets holds the two common channel sets. Spread one into list() or search():
Without a preset or similarity, q runs the default channels: identical, fuzzy, embedded, and lookalike.

List parameters

On list(), the mark_text_* filters and the *_not exclusions take arrays. The SDK sends them as repeated keys (mark_text_is=nike&mark_text_is=mike), never comma-joined, so a comma inside a mark is safe. Values within one key match any; different keys and q must all match. When the query string passes 2 KB, list() sends the same search as a POST.
Both return a SignaList, see Pagination below.

Retrieve and batch

Look up multiple trademarks in one call, by Signa ID or office identifier (max 100 per call):

Pagination

Every list and search method returns a SignaList<T>, which supports three consumption patterns. The first page is fetched eagerly; later pages are fetched lazily. Async iteration, the simplest approach:
Collect to an array with toArray(). It never returns a short array silently. It throws SignaTruncatedError, whose items carry what was collected, in two cases:
  • reason: 'client_limit': no limit was passed and the list holds more than 10,000 items. Pass { limit } for at most that many items, or { limit: Infinity } for all of them.
  • reason: 'server_window': the API ended a trademark search at its 10,000-row search window while more rows match, before your limit was reached. The signal is the API’s result_window_reached warning on the last page; counts alone never make toArray() throw. Narrow the query with filters.
for await and getNextPage() never throw for this; they stop where the API stops (has_more: false).
Manual paging, for full control over when the next request fires:
getNextPage() returns an empty list (not an error) once there are no more pages. Every SignaList exposes data, has_more, request_id, and, on search responses, search_meta and aggregations. There is no public pagination field on the list itself, use has_more and getNextPage() to drive pagination rather than reaching for a cursor directly.

Error handling

All errors extend SignaError. API errors (4xx/5xx) extend SignaAPIError and carry a typed subclass per status code:
Use instanceof to handle specific error types:
Every SignaAPIError carries the structured error body plus the request ID:

Automatic retries

An explicit retryable: false in the server’s error body overrides the status-based rule: a deterministic failure like the watch preview’s 504 timeout is not retried, since a blind retry would re-run the same over-budget work. Retries use exponential backoff with jitter.
Override retry behavior per request:

Timeouts

The default timeout is 30 seconds. Configure it globally or per request:

Debug mode

Logs each request and response (method, URL, status, timing) to stderr.