TypeScript SDK
@yojinhq/jintel-client
The official TypeScript SDK wraps the GraphQL API with typed queries, Zod-validated responses, and a per-request response cache. Works in Node, Bun, Deno, and browsers.
npm install @yojinhq/jintel-client
Quick start
import { JintelClient } from "@yojinhq/jintel-client";
const jintel = new JintelClient({
apiKey: process.env.JINTEL_API_KEY!,
// baseUrl defaults to https://api.jintel.ai/api
});
const quotes = await jintel.quotes(["AAPL", "MSFT"]);
const profile = await jintel.enrichEntity("AAPL");
const batch = await jintel.batchEnrich(
["AAPL", "MSFT", "NVDA"],
["market", "news", "technicals", "earnings", "periodicFilings"],
);
const screen = await jintel.sanctionsScreen("Gazprom", "RU");
// Macro
const gdp = await jintel.gdp("USA", "REAL");
const cpi = await jintel.inflation("USA");
const rates = await jintel.interestRates("USA");
const cape = await jintel.sp500Multiples("SHILLER_PE_MONTH");
All methods return JintelResult<T> — a tagged union (success: true / success: false) so errors are always explicit.
Filtering array sub-graphs
enrichEntity and batchEnrich accept an options object that threads per-field filters into the underlying GraphQL query. Most sub-graphs have a domain-specific filter input with dimensions unique to that data; the generic filter (ArrayFilterInput) covers anything that still takes plain date/limit/sort.
// Generic ArrayFilterInput — research, predictions, discussions, social,
// institutionalHoldings, earningsPressReleases, periodicFilings, and
// market.history/keyEvents/shortInterest.
await jintel.enrichEntity("AAPL", ["research", "market"], {
filter: { since: "2025-01-01", limit: 10, sort: "DESC" },
});
// NewsFilterInput — source + sentiment
await jintel.enrichEntity("AAPL", ["news"], {
newsFilter: { sources: ["CNBC", "finnhub"], minSentiment: 0, limit: 10 },
});
// ExecutivesFilterInput — top-paid officers
await jintel.enrichEntity("AAPL", ["executives"], {
executivesFilter: { minPay: 1_000_000, sortBy: "PAY_DESC", limit: 5 },
});
// InsiderTradeFilterInput — directors only, acquisitions >= $100k
await jintel.enrichEntity("AAPL", ["insiderTrades"], {
insiderTradesFilter: {
isDirector: true,
acquiredDisposed: "ACQUIRED",
minValue: 100_000,
},
});
// EarningsFilterInput — reported beats >= 5%
await jintel.enrichEntity("AAPL", ["earnings"], {
earningsFilter: { onlyReported: true, minSurprisePercent: 5 },
});
// SegmentRevenueFilterInput — product breakdown >= $1B
await jintel.enrichEntity("AAPL", ["segmentedRevenue"], {
segmentedRevenueFilter: { dimensions: ["PRODUCT"], minValue: 1_000_000_000 },
});
// TopHoldersFilterInput — paginated reverse-13F lookup (replaces old positional args)
await jintel.enrichEntity("AAPL", ["topHolders"], {
topHoldersFilter: { limit: 25, offset: 0, minValue: 50_000 },
});
// FinancialStatementFilterInput — annual only
await jintel.enrichEntity("AAPL", ["financials"], {
financialStatementsFilter: { periodTypes: ["12M"], limit: 5 },
});
// SanctionsFilterInput + CampaignFinanceFilterInput under regulatory
await jintel.enrichEntity("Gazprom", ["regulatory"], {
sanctionsFilter: { minScore: 80, programs: ["SDGT"] },
campaignFinanceFilter: { cycle: 2024, party: "DEM" },
});
// FilingsFilterInput — narrow SEC filings by form type
await jintel.enrichEntity("AAPL", ["regulatory"], {
filingsFilter: { types: ["FILING_10K", "FILING_10Q"], limit: 5 },
});
// RiskSignalFilterInput — drop low-severity noise
await jintel.enrichEntity("Gazprom", ["risk"], {
riskSignalFilter: { severities: ["HIGH", "CRITICAL"] },
});
// OptionsChainFilterInput — options chains can exceed 5 000 rows; filter aggressively
await jintel.enrichEntity("BTC", ["derivatives"], {
optionsFilter: {
optionType: "CALL",
strikeMin: 60_000,
strikeMax: 80_000,
minOpenInterest: 100,
sort: "VOLUME_DESC",
limit: 25,
},
});
// FuturesCurveFilterInput — defaults to ASC (nearest contract first)
await jintel.enrichEntity("BTC", ["derivatives"], {
futuresFilter: { limit: 10 },
});
Mix filter fields in a single request — each targets a different sub-graph:
await jintel.batchEnrich(
["AAPL", "MSFT"],
["news", "regulatory", "risk", "earnings"],
{
newsFilter: { sources: ["CNBC"], limit: 5 },
filingsFilter: { types: ["FILING_10K"], limit: 2 },
riskSignalFilter: { severities: ["HIGH", "CRITICAL"] },
earningsFilter: { onlyReported: true, limit: 4 },
},
);
Top-level macro, screen, and short-interest queries
Economics and short-interest still accept the generic filter. sanctionsScreen and campaignFinance accept their domain-specific filters:
await jintel.gdp("USA", "REAL", { since: "2010-01-01", limit: 20 });
await jintel.inflation("USA", { since: "2020-01-01" });
await jintel.interestRates("USA", { limit: 12 });
await jintel.sp500Multiples("SHILLER_PE_MONTH", { limit: 60 });
await jintel.shortInterest("GME", { limit: 5 });
await jintel.sanctionsScreen("Gazprom", "RU", { minScore: 80, listNames: ["SDN"] });
await jintel.campaignFinance("Acme PAC", 2024, { party: "DEM", minRaised: 100_000 });
Filter defaults
| Filter | Default limit | Default sort |
|---|---|---|
ArrayFilterInput | 20 | DESC |
NewsFilterInput | 20 | DESC (by date) |
ExecutivesFilterInput | 20 | PAY_DESC |
InsiderTradeFilterInput | 20 | DESC (by transactionDate) |
EarningsFilterInput | 20 | DESC (by reportDate) |
SegmentRevenueFilterInput | 20 | DESC (by filingDate) |
TopHoldersFilterInput | 20 (offset 0) | DESC (by value) |
FinancialStatementFilterInput | 20 | DESC (by periodEnding) |
SanctionsFilterInput | 20 | DESC (by score) |
CampaignFinanceFilterInput | 20 | DESC (by totalRaised) |
FilingsFilterInput | 20 | DESC |
RiskSignalFilterInput | 20 | DESC |
FuturesCurveFilterInput | 50 | ASC |
OptionsChainFilterInput | 100 | EXPIRATION_ASC |
Omitting a filter returns the full upstream set (no defaults applied). Setting any filter field applies that input's defaults for the remaining dimensions.
Migrating from 0.20 → 0.21
topHolders: { limit, offset }option was removed. UsetopHoldersFilter: { limit, offset, minValue, since, until, sort }instead.- The generic
filteroption no longer threads intonews,insiderTrades,earnings,segmentedRevenue, orfinancials.*. Use the new domain-specific filter options (newsFilter,insiderTradesFilter,earningsFilter,segmentedRevenueFilter,financialStatementsFilter). sanctionsScreenandcampaignFinanceroot methods accept an optional third argument with their new filter inputs.
See Filtering & sorting for the underlying GraphQL inputs.
Response caching
Enable the in-process TTL cache to deduplicate identical calls within short windows — 30s for quotes, 5min for enrich / price history by default:
const jintel = new JintelClient({
apiKey: process.env.JINTEL_API_KEY!,
cache: { quotesTtlMs: 15_000, enrichTtlMs: 120_000 },
});
jintel.invalidateCache(["AAPL"]); // after an external signal event