Runnable TypeScript examples for alphai-sdk — the typed client for the AlphAI REST API: relevance-scored, ticker-linked financial news plus SEC Form 4 insider data.
Each script is small, self-contained, and runs against the live API. Together they cover news and symbol endpoints, Earnings, Brief, Radar, async pagination, parallel composition, typed errors, and rate-limit inspection.
The SDK has zero runtime dependencies and runs on Node ≥18, browsers, edge, Deno, and Bun. These examples use
tsxto run TypeScript directly and Node's built-in.envloader, so the only runtime dependency here is the SDK itself; the remaining dependencies are dev tooling. Running this repository requires Node ≥20.12, includingprocess.loadEnvFile(). The examples targetalphai-sdk0.6.x.
# 1. install
npm install
# 2. add your API key (get one at https://alphai.io/account/api-keys)
cp .env.example .env
# then edit .env and paste your ak_live_… key
# 3. run any example
npm run quickstart
npm run dashboard -- TSLANo .env? Pass the key inline instead:
ALPHAI_API_KEY=ak_live_… npm run quickstart| Script | Command | What it shows |
|---|---|---|
01-quickstart.ts |
npm run quickstart |
Construct a client, news.list() with filters, read the enriched fields. |
02-paginate.ts |
npm run paginate |
news.iterate() async generator with a maxItems cap; tally categories while streaming. |
03-trending.ts |
npm run trending |
news.trending() — top stories of the last 48h. |
04-ticker-dashboard.ts |
npm run dashboard |
Compose four endpoints in parallel into one report. |
05-insider.ts |
npm run insider |
symbols.insiderSummary() (decimal-string money) + the insider news feed. |
06-errors-and-ratelimits.ts |
npm run errors |
Typed error hierarchy + client.lastRateLimit. |
07-symbols.ts |
npm run symbols |
symbols.list() discovery and symbols.get() detail. |
08-earnings.ts |
npm run earnings |
Filing-verified earnings and missing latest reads (HTTP 204). |
09-brief.ts |
npm run brief -- NVDA,AMD |
Multi-ticker Brief and truncation flags. |
10-radar.ts |
npm run radar |
Radar snapshot, freshness and tier delay. |
Most scripts take an optional ticker argument:
npm run quickstart -- NVDA
npm run dashboard -- MSFT
npm run insider -- AAPLType-check everything without running:
npm run typecheck
npm test # offline polling/delivery regressions, no key or networkGitHub Actions runs both checks on Node 20, 22, and 24.
A small, deployable service that turns the SDK into a financial-news alerting bot. Each poll it fetches the feed for your watchlist, keeps only the unseen high-relevance stories, and pushes them to Telegram, Slack, and/or any webhook — deduplicating successful delivery while UIDs remain in the local store.
# Poll once (cron / GitHub Actions friendly), console output:
npm run alerts
# Long-lived: poll every POLL_INTERVAL_SECONDS until Ctrl-C:
npm run alerts:watch
# Format real alerts with your AlphAI key; no messaging tokens needed:
npm run alerts -- --dry-run --backfill=3Channels are configured by env (see .env.example); each is
active only when its variables are set. Console output is always on for local
visibility. --dry-run fetches real API data but delivers only to the console.
It uses separate state (STATE_FILE + .dry-run) so previews do not suppress
later remote delivery.
| Channel | How to enable |
|---|---|
| Console | always on (and the only channel under --dry-run) |
| Telegram | TELEGRAM_BOT_TOKEN + TELEGRAM_CHAT_ID (Bot API sendMessage, HTML) |
| Slack | SLACK_WEBHOOK_URL (Incoming Webhook, blocks + fallback text) |
| Webhook | WEBHOOK_URL (POSTs { "event": "alphai.news.alert", "alert": {…} }) |
Tuning (all optional, with defaults):
| Env | Default | Meaning |
|---|---|---|
WATCHLIST |
NVDA,AAPL,MSFT,TSLA |
Tickers to watch, or trending for whole-market mode |
MIN_RELEVANCE |
7 |
Minimum relevance score (1–10) to alert |
CATEGORIES / EXCLUDE_CATEGORIES |
— | Restrict / drop news categories |
PER_TICKER_LIMIT |
5 |
Max articles per ticker per poll (1–20) |
POLL_INTERVAL_SECONDS |
300 |
Cadence in --watch mode |
STATE_FILE |
.alerts-state.json |
Where the seen-uid dedup state is stored |
FIRST_RUN_BACKFILL |
0 |
On first run, deliver N newest; the rest seed silently |
First-run behavior. With no state file yet, the bot establishes a baseline
— it marks current articles as seen without alerting, so you don't get blasted
with the backlog. Pass --backfill=N (or FIRST_RUN_BACKFILL) to deliver the N
newest on that first run instead.
How the pieces fit:
alerts/
├── index.ts # CLI setup; run once or --watch
├── polling.ts # fetch → filter unseen → deliver → persist
├── config.ts # env + CLI flags → typed AppConfig
├── store.ts # SeenStore: capped, persisted set of delivered article UIDs (dedup)
├── format.ts # RichNewsArticle → normalized Alert → per-channel renderers
└── notifiers.ts # Console / Slack / Telegram / Webhook (native fetch, zero deps)
Deploy it on a cron or run npm run alerts:watch under your supervisor of choice.
The default four tickers every 300 seconds use about 1,152 requests/day before
retries, exceeding Free's 100/day. On Free, set POLL_INTERVAL_SECONDS=3600
(96/day for four tickers), use fewer tickers, or poll less often. Other examples
and retries share that daily budget.
This app samples one recent page per ticker; trending samples a ranked snapshot.
Both modes apply the configured relevance and category filters. Busy periods and
late arrivals can be missed. For complete incremental ingestion, use
news.list({ sort: "ingested", ... }), drain pages, persist cursors and add a
durable delivery outbox.
A story is marked seen only after every channel succeeds. Failed stories retry while still present in the fetched sample; a channel that already succeeded may receive a duplicate on retry. One-shot runs exit non-zero on fetch or delivery failure. This is not a durable queue.
The store retains 5,000 UIDs. Run one process per state file, preserve it across
cron/Actions runs, and use a new file when changing the watchlist or filters.
Repeated previews also deduplicate; remove only the .dry-run state to preview
the same batch again.
import { AlphaAI } from "alphai-sdk";
const client = new AlphaAI(); // reads ALPHAI_API_KEY from the environment
// One page of NVDA news, only the high-relevance items.
const page = await client.news.list({ symbol: "NVDA", minRelevance: 7 });
for (const article of page.results) {
console.log(`[${article.enrichment.relevance_score}] ${article.original.title}`);
}
// Auto-paginate — the generator follows next_cursor for you.
for await (const a of client.news.iterate({ symbol: "NVDA", maxItems: 100 })) {
// …
}
// Compose endpoints in parallel.
const [detail, sentiment, insider] = await Promise.all([
client.symbols.get("AAPL"),
client.symbols.sentimentSummary("AAPL"),
client.symbols.insiderSummary("AAPL"),
]);An exported ALPHAI_API_KEY takes precedence over .env. If it is stale, run
unset ALPHAI_API_KEY in your shell to use the key from .env.
- Money is decimal strings. Fields like
buy_value_usdandnet_valueare returned as strings (e.g."1284500.00") and never coerced tonumber— JS floats lose precision on large dollar amounts. Use a big-decimal library if you need arithmetic. Timestamps are ISO 8601 strings (no auto-Date). Symboltype shadows the global. The symbol model is exported asSymbol. Alias it when importing:import type { Symbol as AlphaSymbol } from "alphai-sdk";- Retries are automatic. Idempotent GETs retry on 429 / 5xx / network errors
with exponential backoff (configurable
maxRetries, default 2;0to disable). - Rate limits are per account and two-layer — a per-minute burst plus a
per-day volume cap (Free 20/min + 100/day · Basic 60/min + 10,000/day ·
Pro 150/min + 100,000/day). Read
client.lastRateLimitafter any keyed call; theX-RateLimit-*headers report the daily layer, which resets at 00:00 UTC. - Never commit your key.
.envis git-ignored; only.env.exampleis tracked.
- SDK on npm — https://www.npmjs.com/package/alphai-sdk
- AlphAI — https://alphai.io
- API keys — https://alphai.io/account/api-keys