Skip to content

TypeScript SDK

@theneuralledger/sdk is a typed client for the intelligence API. It handles authentication, retries, timeouts, and rate limit headers, and its types are generated from the published OpenAPI schema, so responses stay in step with the API.

bash
npm install @theneuralledger/sdk

Requires Node 20 or newer, or any runtime with a global fetch.

Quick start

ts
import { TnlClient } from '@theneuralledger/sdk';

const tnl = new TnlClient({ apiKey: process.env.TNL_API_KEY! });

const page = await tnl.listNews({ page_size: 10, sort: 'pipeline' });
for (const story of page.data) {
  console.log(story.publishedAt, story.title);
}

Client options

ts
const tnl = new TnlClient({
  apiKey: process.env.TNL_API_KEY!,
  baseUrl: 'https://theneuralledger.com', // default
  timeoutMs: 30_000,                          // default
  retries: 2,                                 // retries on 429 and 5xx
  userAgent: 'acme-research/1.4',             // identify your integration
  requestId: crypto.randomUUID(),             // echoed back for support
  fetch: undefined,                           // inject your own for tests
});

Setting a distinctive userAgent is worth doing — it is what support looks at when tracing a request.

Reading news

ts
// Newest first
const latest = await tnl.listNews({ sort: 'pipeline', page_size: 25 });

// Filtered
const japan = await tnl.listNews({
  country: 'Japan',
  category: 'Economic & Macro',
  published_since: '2026-07-01T00:00:00Z',
});

// Only the fields you need — smaller responses, less quota
const slim = await tnl.listNews({
  fields: 'id,title,publishedAt,impactPaths',
  page_size: 100,
});

Pagination

Cursor pagination is stable while new stories arrive; offsets shift underneath you. Prefer cursors for anything that walks more than one page.

ts
async function* everyStory(since: string) {
  let cursor: string | undefined;
  do {
    const page = await tnl.listNews({ published_since: since, page_size: 100, cursor });
    yield* page.data;
    cursor = page.page?.next_cursor ?? undefined;
  } while (cursor);
}

for await (const story of everyStory('2026-07-01T00:00:00Z')) {
  await save(story);
}

Search and discovery

ts
const hits = await tnl.searchNews({ q: 'tariff', page_size: 20 });

const entities = await tnl.listEntities({ q: 'Federal Reserve' });
const paths = await tnl.listImpactPaths({ q: 'oil' });

const byEntity = await tnl.getEntityStories('Bank of Korea');
const byAsset = await tnl.getAssetStories('KRW');
const byPath = await tnl.getImpactPathStories('policy rate -> currency');

Saved searches

ts
const saved = await tnl.createSavedSearch({
  name: 'JP macro',
  query: { country: 'Japan', category: 'Economic & Macro' },
});

const results = await tnl.getSavedSearchResults(saved.data.id);
await tnl.updateSavedSearch(saved.data.id, { name: 'Japan macro' });
await tnl.deleteSavedSearch(saved.data.id);

Ledger AI Terminal

ts
const answer = await tnl.askAiTerminal({
  question: 'What drove the won this week?',
});
console.log(answer.data.text);

Answers are grounded in indexed stories and cite their sources. This consumes AI quota rather than ordinary request quota — see plans.

Rate limits

After any call, lastRateLimit carries what the server reported:

ts
await tnl.listNews({ page_size: 1 });
console.log(tnl.lastRateLimit); // { limit, remaining, resetAt }

The client already retries 429 and 5xx responses with backoff, honouring Retry-After. Use lastRateLimit to pace bulk work before you get throttled:

ts
if ((tnl.lastRateLimit?.remaining ?? Infinity) < 10) {
  await new Promise((r) => setTimeout(r, 60_000));
}

Errors

ts
import { TnlError, TnlRateLimitError, TnlAuthenticationError } from '@theneuralledger/sdk';

try {
  await tnl.listNews({ page_size: 1 });
} catch (error) {
  if (error instanceof TnlRateLimitError) {
    // exhausted after the built-in retries
  } else if (error instanceof TnlAuthenticationError) {
    // key missing, revoked, or wrong tenant
  } else if (error instanceof TnlError) {
    console.error(error.status, error.code, error.requestId);
  } else {
    throw error;
  }
}

Include requestId when reporting a problem — it identifies the exact request in our logs.

Other methods

getNews(idOrSlug) for a single story, plus getAccount, getFilters, getFeed, getMarkets, listSavedSearches, getSavedSearch. TnlTimeoutError is raised when a request exceeds timeoutMs. Full parameters are in the API reference; the SDK mirrors it and the types are generated from the same schema.

The Neural Ledger API