New: unified TypeScript, Python & Rust SDKs — available now in beta.

TypeScript SDK

Build with the official Forecite TypeScript / Node.js SDK.

The official TypeScript SDK gives you a single typed surface across the Forecite scored feed, the Verdict Engine, reference data, webhooks, and the realtime stream. It runs in Node.js and any modern runtime with fetch and WebSocket.

Beta

The TypeScript SDK is in beta while we harden the surface ahead of a stable 1.0. Method names and shapes may still change.

One Forecite client exposes every resource as a namespace — forecite.feeds, forecite.providers, forecite.score, forecite.stream — all authenticated with a single API key.

Quickstart

Install the package

npm install @forecite/sdk

Create a client

Pass your fc_live_… key (get one from the API keys page). Keep it server-side.

import { Forecite } from "@forecite/sdk"

const forecite = new Forecite(process.env.FORECITE_API_KEY!)

Fetch scored feeds

const { data, next_cursor } = await forecite.feeds.list({
  symbol: "NVDA",
  actionability: true,
  limit: 10,
})

for (const item of data) {
  console.log(item.title, item.scoring.sentiment_score)
}

SDK patterns

The client uses consistent patterns for configuration, pagination, and errors across every resource.

Response models

Reads return typed models with snake_case fields matching the API. A feed item carries the source artifact plus its Verdict Engine scoring block:

interface FeedItem {
  id: string
  title: string | null
  link: string | null
  source: string
  published_at: string
  scraped_at: string
  scoring: {
    actionability: boolean | null
    actionability_comment: string | null
    sentiment_score: number | null // 0–10 (5 = neutral)
    sentiment_comment: string | null
  }
  symbols: { symbol: string; exchange: string | null }[]
}

Environment configuration

Production is the default. Pass baseUrl / wsUrl to target local dev or a custom deployment.

const forecite = new Forecite({
  apiKey: process.env.FORECITE_API_KEY!,
  baseUrl: "http://localhost:3000/api",
  wsUrl: "ws://localhost:8080",
})

Pagination

List endpoints return { data, next_cursor }. Pass next_cursor back as cursor to page; a null cursor means you've reached the end.

let cursor: string | null | undefined
do {
  const page = await forecite.feeds.list({ limit: 100, cursor })
  for (const item of page.data) handle(item)
  cursor = page.next_cursor
} while (cursor)

Error handling

Every failed request throws a ForeciteError carrying the HTTP status and the API's code / message.

import { Forecite, ForeciteError } from "@forecite/sdk"

try {
  const page = await forecite.feeds.list({ limit: 10 })
} catch (err) {
  if (err instanceof ForeciteError) {
    if (err.status === 429) {
      // Rate limited — retry with backoff.
    } else if (err.status === 401) {
      // Bad or missing API key.
    }
  }
  throw err
}

Feed data

Read the scored feed — list with filters, or fetch a single item by id.

// Filtered list — actionable NVDA items, most bullish first
const { data } = await forecite.feeds.list({
  symbol: "NVDA",
  actionability: true,
  sentiment_min: 7,
})

// One item with full per-symbol detail
const item = await forecite.feeds.get("0b3f2c1e-…")

Available filters: since / until (ISO 8601), symbol, exchange, aggregator, actionability, sentiment_min / sentiment_max, limit, cursor.

Discovery

Browse the reference data that powers the feed's filters.

const providers = await forecite.providers.list()
const one = await forecite.providers.get(providers[0].id)
const sources = await forecite.sources.list() // string[]
const activity = await forecite.sources.get("globenewswire")
const symbols = await forecite.symbols.list({ limit: 500 })
const nvda = await forecite.symbols.get("NVDA")
const byDimension = await forecite.tags.list()
const corpActivity = await forecite.tags.get("corp_activity")

Scoring

Run the Verdict Engine on your own text. Pass an artifact and optional scoring options.

const verdict = await forecite.score(
  {
    type: "filing",
    title: "Acme cuts FY guide on softening demand",
    body: "Acme Corp lowered its full-year revenue outlook…",
    related_symbols: ["ACME"],
  },
  { model: "pro", score_sentiment: "if_actionable" },
)

console.log(verdict.actionability.score, verdict.sentiment?.short_direction)

Realtime streams

Subscribe to the scored feed over WebSocket. The stream auto-reconnects and can replay a snapshot of the latest matching items before going live.

const stream = forecite.stream(
  { filters: { symbols: ["NVDA", "TSLA"], actionable: true }, snapshot: 10 },
  {
    onWelcome: ({ tier }) => console.log("connected:", tier),
    onFeed: (item, { snapshot }) => {
      console.log(snapshot ? "backfill" : "live", item.title)
    },
    onQuotaExceeded: ({ message }) => console.warn(message),
    onError: (err) => console.error(err),
  },
)

// stream.ping()  — app-level keepalive
// stream.close() — stop and disable reconnect

WebSocket runtime

A global WebSocket is required — Node 22+, a browser, or a polyfill.

Account

Inspect the authenticated key and its usage.

const key = await forecite.me() // tier, limits
const usage = await forecite.usage({ days: 14 }) // daily feed vs. score usage

Webhooks

Manage outbound webhook endpoints.

const hook = await forecite.webhooks.create({
  url: "https://example.com/forecite",
  description: "prod",
})

await forecite.webhooks.list()
await forecite.webhooks.update(hook.id, { enabled: false })
await forecite.webhooks.delete(hook.id)

Changelog

0.1.2

  • First public beta of @forecite/sdk.
  • Typed clients for feeds, scoring, discovery, account, webhooks.
  • Auto-reconnecting realtime feed stream with snapshot replay.

On this page