EarlyForge

JavaScript SDK

earlyforge-pulse-sdk — a zero-dependency, fetch-based client for the free Pulse API.

earlyforge-pulse-sdk is a zero-dependency JavaScript/TypeScript client for the Pulse API — the same free, authenticated daily snapshot documented on that page. It wraps the 4 Pulse endpoints only; it is not a client for EarlyForge's paid real-time Trends detection catalog, articles, briefs, or alerts APIs.

It uses the global fetch, so it works in Node 18+ and in browsers with no other dependency.

Source: tools/sdk-js-earlyforge — read the package's own README for anything not covered here.

Install

Not published to npm yet — install from a clone of the repository:

git clone https://github.com/earlyforge/earlyforge.git
cd earlyforge/tools/sdk-js-earlyforge
npm install
npm run build
npm link   # or: npm pack and install the tarball elsewhere

A published npm install earlyforge-pulse-sdk package is coming.

Quickstart

ESM (Node or browser)

import { PulseClient } from "earlyforge-pulse-sdk"
 
const client = new PulseClient("ef_live_xxxxxxxxxxxxxxxx")
const snapshot = await client.topTrends({ locale: "fr" })
console.log(snapshot.trends[0])

CommonJS

const { PulseClient } = await import("earlyforge-pulse-sdk")
const client = new PulseClient("ef_live_xxxxxxxxxxxxxxxx")
const snapshot = await client.topTrends()

The package ships ESM-only — a CommonJS require() consumer loads it via a dynamic import(), as shown above.

Get a key from Settings → API Keys in the console — any account works, Pulse access is free.

Methods

new PulseClient(apiKey, options?: { baseUrl?: string })

Constructs the client. Throws if apiKey is empty.

topTrends({ date?, locale? }): Promise<TrendListResponse>

Global top trends — same daily snapshot as the Pulse homepage.

const { trends, total, cached_at, cache_ttl_seconds } = await client.topTrends()

trendsByRegion(region, { date?, locale? }): Promise<TrendListResponse>

Top trends for an ISO 3166-1 alpha-2 region code (e.g. "US", "FR"). Same TrendListResponse shape as topTrends.

trendsByCategory(category, { date?, locale? }): Promise<TrendListResponse>

Top trends for a category (e.g. "politics", "tech"). Same TrendListResponse shape as topTrends.

getTrend(trendId): Promise<TrendDetailResponse>

Detail for one trend. Same fields as a trend entry, plus canonical_name, sources, a full description, and a timeline of {ts, score, sources_count} points.

Error handling

Every non-2xx response rejects with a PulseApiError carrying statusCode and detail — mirroring the OpenAPI contract's 401 (missing/invalid/revoked key), 404 (unknown trend), and 502 (upstream unavailable) responses. Network failures also reject with PulseApiError.

import { PulseApiError } from "earlyforge-pulse-sdk"
 
try {
  await client.getTrend("does-not-exist")
} catch (error) {
  if (error instanceof PulseApiError) {
    console.error(error.statusCode, error.detail)
  }
}

Rate limits

No monthly call quota on this surface, for any plan — only the shared 60 requests/60 seconds burst limit applies, same as the anonymous Pulse page.

Going further

This SDK only covers the free Pulse snapshot — it's the entire public API, on every plan. EarlyForge's paid plans add real-time trend detection across the full catalog of countries and categories inside the app itself (console only, not via this SDK) — see the pricing page for that upgrade path.