Integrate
TypeScript SDK
@fomoquant/sdk is a zero-dependency, fully typed client: fetch, global WebSocket and WebCrypto only. Responses are typed snake_case objects identical to the REST JSON.Install
pnpm add @fomoquant/sdkRuns in Node ≥ 22, Bun, Deno, Cloudflare Workers / Vercel Edge and browsers (keep keys out of browsers you do not control — anything shipped to a browser is public).
Create a client
import { FomoQuant } from "@fomoquant/sdk";
const fq = new FomoQuant({
apiKey: process.env.FOMOQUANT_API_KEY!, // fq_live_…
baseUrl: "https://fomoquant.app",
});Options
| Name | Description |
|---|---|
apiKeyrequiredstring | fq_live_… (live dataset). |
baseUrlstring | API origin (this deployment: https://fomoquant.app).Default https://fomoquant.app |
streamUrlstring | Pin the WebSocket URL. By default stream() discovers it from GET {baseUrl}/v1/stream/info before every (re)connect. |
fetchtypeof fetch | Custom fetch (tests, proxies). |
timeoutMsnumber | Per-request timeout.Default 30000 |
maxRetriesnumber | Automatic retries on 429 honouring Retry-After (max 5).Default 2 |
apiKeystringrequiredfq_live_…(live dataset).baseUrlstringAPI origin (this deployment:https://fomoquant.app).Defaulthttps://fomoquant.appstreamUrlstringPin the WebSocket URL. By default stream() discovers it from GET {baseUrl}/v1/stream/info before every (re)connect.fetchtypeof fetchCustom fetch (tests, proxies).timeoutMsnumberPer-request timeout.Default30000maxRetriesnumberAutomatic retries on 429 honouring Retry-After (max 5).Default2
Methods
tokens
fq.tokens.get(ref)TokenQuantQuant snapshot. ref: "$XYZ", "XYZ", "tk_…", "<chain>:<address>" or "<address>". Reference
fq.tokens.list({ sort?, dir?, limit?, cursor?, narrative?, chain?, q? })List<TokenRow>Tokens with current scores. Reference
fq.tokens.analogs(ref, { k? })TokenAnalogsNearest historical setups (no lookahead). Reference
fq.scanner.run({ preset?, rules?, sort?, sort_dir?, limit?, chains?, narrative? })ScanResultRun scanner rules; null values never pass. Reference
signals
fq.signals.list({ min_score?, signal_type?, chain?, market_cap?, liquidity?, created_after?, status?, token?, limit?, cursor? })List<Signal>The signal feed. min_score accepts { field, value } or "momentum:70". Reference
fq.signals.get(id)SignalDetailConditions, feature snapshot, analogs, prior firings, rule doc. Reference
fq.signals.iterate(params)AsyncGenerator<Signal>Every matching signal across pages.
users, cohorts, narratives
fq.users.get(handle)UserQuantPoint-in-time author metrics. Leading @ is optional. Reference
fq.cohorts.list({ kind? })List<Cohort>Algorithmic cohorts plus your own. Reference
fq.cohorts.get(id)CohortMembers, activity, convergence events. Reference
fq.narratives.list()List<Narrative>Narrative map. Reference
fq.narratives.get(slug)NarrativeOne narrative. Reference
fq.narratives.rotation({ window? })NarrativeRotationAttention-share change (24h | 7d). Reference
fq.narratives.heatmap({ metric?, bucket?, range? })NarrativeHeatmapNarrative × time matrix. Reference
research
fq.backtests.create({ rules, horizon, name?, from?, to?, cooldown?, dead_token_policy?, universe? })BacktestRunQueue a backtest (202). Scope backtests:write, Pro / Team. Reference
fq.backtests.get(id)BacktestRunCurrent state of a run. Reference
fq.backtests.wait(id, { intervalMs?, timeoutMs?, signal? })BacktestRunPoll with backoff until done or failed (default timeout 5 min).
fq.eventStudies.list()List<EventStudy>All event studies. Reference
fq.eventStudies.get(slug)EventStudyOne event study. Reference
webhooks & realtime
fq.webhooks.create({ url, events })WebhookCreatedRegister an endpoint; secret returned once. Reference
fq.webhooks.list()List<Webhook>Webhooks for this key's dataset. Reference
fq.webhooks.delete(id)DeletedDelete a webhook. Reference
fq.webhooks.test(id)WebhookTestResultSend a signed webhook.test now. Reference
fq.stream({ events, tokens?, onEvent, onError? })StreamHandleWebSocket stream with automatic reconnect + resubscribe; handle.close(). Reference
FomoQuant.verifyWebhook(secret, rawBody, signatureHeader, toleranceSec?)Promise<WebhookEvent>Static. Verify and parse a delivery (default tolerance 300 s). Reference
meta & helpers
fq.key()KeyInfoMode, dataset, scopes, rate limit and plan of the key. Reference
fq.models()ModelCatalogScore and signal definitions and versions. Reference
fq.health()HealthProvider status, freshness and the current stream URL. Reference
fq.streamInfo()StreamInfoWhere the realtime WebSocket lives right now (stream() resolves it for you). Reference
fq.paginate(fetchPage)AsyncGenerator<T>Iterate any cursor-paginated list.
fq.request(method, path, { query?, body?, signal? })Promise<T>Low-level call with auth, retries and typed errors.
fq.lastResponseRequestMeta | nullStatus, request id and rate-limit headers of the last response.
fq.mode"live" | "test"Derived from the key prefix.
Pagination
Lists return { object: "list", data, has_more, next_cursor }. Pass cursor to continue, or iterate:
for await (const s of fq.signals.iterate({ signal_type: ["EARLY_ACCELERATION"] })) {
console.log(s.token.symbol, s.fired_at, s.analogs?.n);
}
// any list
for await (const t of fq.paginate((cursor) => fq.tokens.list({ sort: "momentum", cursor }))) {
console.log(t.token.symbol, t.scores.momentum);
}Errors & retries
import { FomoQuantError } from "@fomoquant/sdk";
try {
await fq.tokens.get("$NOPE");
} catch (e) {
if (e instanceof FomoQuantError) console.log(e.status, e.code, e.message, e.requestId);
}FomoQuantError carries code, status, message, requestId, details and retryAfter. Codes mirror the API (error table) plus NETWORK and TIMEOUT (status 0). 429 responses are retried automatically up to maxRetries, waiting for Retry-After.
Realtime stream
const stream = fq.stream({
events: ["signal.created", "score.updated", "cohort.convergence", "narrative.shift"],
tokens: ["$XYZ"], // optional; applies to token-scoped events
onEvent(ev) {
if (ev.event === "score.updated") console.log(ev.data.symbol, ev.data.scores.momentum);
},
onError: (err) => console.warn(err.code, err.message),
});
// later
stream.close();Requires scope stream:read. The realtime host is separate from the REST API and its address can change, so stream() resolves it from /v1/stream/info before every (re)connect; while that host is offline you get a STREAM_UNAVAILABLE error in onError and the SDK keeps retrying with backoff. The connection receives only the key's dataset, reconnects with backoff and resubscribes. In Node the key travels in the Authorization header; browsers cannot set headers, so the SDK uses ?key= there — use a key that has only the stream:read scope. Protocol details are in the API reference.
Webhooks
Use FomoQuant.verifyWebhook(secret, rawBody, signatureHeader) on the raw request body; it throws on a bad or stale signature and returns the typed event. See Webhooks.
FomoQuant provides analytics and historical/statistical context, not financial advice or guaranteed predictions.