Skip to content

Quick Start ​

This page builds a company feed, reads its diagnostics, runs a topic feed over a date window, and turns the same query into a watcher. Install the package first (Installation); every example is an ES module that uses top-level await.

1. Build a company feed ​

ts
import { buildCompanyNewsFeedResult } from "@xbbg/xnews";

const result = await buildCompanyNewsFeedResult({
  ticker: "JPM",
  companyName: "JPMorgan Chase",
  // Required for sec.gov. Identify your application and a real contact address.
  secUserAgent: "my-app/1.0 ops@example.com",
  limit: 25,
});

for (const item of result.items.slice(0, 5)) {
  console.log(`${item.publishedAt ?? "undated"}  [${item.provider}]  ${item.title}`);
  console.log(`  ${item.url}`);
}

Without sources, a company feed queries sec-edgar, yahoo-finance, google-news, and finviz concurrently, merges duplicates, sorts newest first, and keeps the first limit items.

2. Read the diagnostics ​

buildCompanyNewsFeedResult returns a NewsFeedResult:

FieldMeaning
subjectThe normalized subject: kind, key, displayName, plus ticker, companyName, cik, or query
itemsMerged NewsItem[], newest first, capped by limit
providersOne ProviderResult per requested provider: status, itemCount, items, warnings, requestUrls, fetchedAt, durationMs, undatedExcluded, and error
warningsEvery provider warning, flattened
partialtrue when any provider finished error, unsupported, partial, or disabled
fetchedAtISO timestamp of the request
ts
import { buildCompanyNewsFeedResult } from "@xbbg/xnews";

const result = await buildCompanyNewsFeedResult({
  ticker: "JPM",
  companyName: "JPMorgan Chase",
  secUserAgent: "my-app/1.0 ops@example.com",
});

console.table(
  result.providers.map(({ provider, status, itemCount, durationMs, error }) => ({
    provider,
    status,
    itemCount,
    durationMs,
    error: error ? `${error.code}: ${error.message}` : "",
  })),
);

if (result.partial) {
  console.warn("Incomplete feed:", result.warnings);
}

A provider that fails does not fail the call. For example, leaving out secUserAgent makes sec-edgar report status: "disabled" with an error.code of "config" and a warning that names the missing setting, while the other providers still return items. See Errors & Statuses for every status and code.

Fail loudly instead

The array-returning builders (buildCompanyNewsFeed, buildTopicNewsFeed, buildNewsFeed, buildWatchlistNewsFeed) accept strict: true, which throws if any provider produced a warning.

3. Query a topic over a date window ​

ts
import { buildTopicNewsFeedResult } from "@xbbg/xnews";

const lastWeek = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000);

const topic = await buildTopicNewsFeedResult({
  query: "bank capital requirements",
  sources: ["google-news", "federal-register", "federal-reserve", "fdic", "occ"],
  since: lastWeek,
  limit: 30,
});

for (const item of topic.items) {
  console.log(item.publishedAt, item.source, item.title);
}

Topic feeds default to google-news only; pass sources to fan out. federal-register queries its API, while federal-reserve, fdic, and occ are fixed feeds that are fetched whole and filtered locally: every query token must appear in the title or summary. since and until are inclusive, accept ISO strings or Date objects, and drop undated items (counted in ProviderResult.undatedExcluded).

4. Watch for new items ​

Every feed has a watcher: an async generator that polls on an interval and yields only items it has not seen before.

ts
import { createNewsWatcher } from "@xbbg/xnews";

const controller = new AbortController();
process.once("SIGINT", () => controller.abort());

try {
  for await (const fresh of createNewsWatcher({
    ticker: "JPM",
    companyName: "JPMorgan Chase",
    secUserAgent: "my-app/1.0 ops@example.com",
    intervalMs: 5 * 60_000,
    signal: controller.signal,
  })) {
    for (const item of fresh) console.log("new:", item.publishedAt, item.title);
  }
} catch (error) {
  // Aborting during the sleep between polls rejects with the abort reason.
  if (!controller.signal.aborted) throw error;
}

The first poll yields everything currently in the feed; later polls yield only unseen items. A watcher throws if every provider fails on a poll, so an outage cannot look like a quiet feed. To survive restarts, persist the ids you have processed and pass them back as seenIds (Watchlists & Watchers).

Where to go next ​

xbbg is independent open-source software and is not affiliated with, endorsed by, sponsored by, or approved by Bloomberg Finance L.P.