import type { DebtMaturitiesPayload } from "./debt-maturities"; import type { CryptoMarketsPayload } from "./crypto-markets"; import type { CentralBankRatesPayload } from "./central-bank-rates"; import type { EstimateRevisionsPayload } from "./estimate-revisions"; import type { MoneyMarketsPayload } from "./money-markets"; import type { ShortVolumePayload, ShortVolumeScope } from "./short-volume"; import type { FuturesCurvePayload } from "./futures-curve"; import type { CotBoardPayload, CotContractPayload, CotFamily, CotClass } from "./cot"; import type { TapeSnapshot } from "./tape"; import type { ExchangeRateSnapshot } from "../types/exchange-rate"; import type { RatePathPayload } from "./rates"; import type { TickerFinancials } from "../types/financials"; import type { InstrumentSearchResult } from "../types/instrument"; import { normalizeSavedSearchHits, normalizeSavedSearchResponse, normalizeSearchResponse, normalizeTweetSearchResponse, } from "./normalizers"; import { cloudCdsPath, cloudCongressHousePath, cloudEarningsCallsPath, cloudEarningsTranscriptPath, cloudJobsMoversPath, cloudJobsPath, cloudJobsPostingsPath, type CloudJobsPostingsParams, publicProxyStatementPath, publicFilingEventsPath, publicRiskReportPath, publicRiskReportsPath, publicProxyStatementsPath, cloudExchangeRatePath, cloudSec13FPath, cloudSecFilingContentPath, cloudSecFilingDocumentsPath, cloudSecFilingsPath, cloudFredSeriesPath, cloudShillerPath, cloudHistoryPath, cloudMarketSearchPath, cloudMarketSymbolPath, cloudNewsPath, cloudOptionsChainPath, cloudSavedSearchHitsPath, cloudSavedSearchPath, cloudSavedSearchesPath, cloudSearchDocumentPath, cloudSearchPath, cloudStatementsPath, cloudTickerTweetsPath, cloudTweetSearchPath, type CloudCdsParams, type CloudCongressHouseParams, type CloudEarningsCallsParams, type CloudFredSeriesParams, type CloudHistoryParams, type CloudNewsParams, type CloudSearchParams, type CloudSecFilingParams, type CloudSecFilingsParams, type CloudTickerTweetsParams, type CloudTweetSearchParams, } from "./paths"; import type { CloudAnalystResearchPayload, CloudShortInterestPayload, CloudCdsResponse, CloudCompanyProfile, CloudCongressHousePayload, CloudEarningsCallListPayload, CloudEarningsTranscriptPayload, CloudJobsMoversPayload, CloudJobsPostingsPayload, CloudJobsResponse, CloudProxyStatementListPayload, CloudProxyStatementPayload, CloudFilingEventPayload, CloudRiskReportListPayload, CloudRiskReportPayload, CloudCorporateActionsPayload, CloudEconEventPayload, CloudEquityDiagnosticMode, CloudEquityDiagnosticResult, CloudFredSeriesPayload, CloudShillerPayload, CloudFundamentals, CloudFinancialsPayload, CloudHoldersPayload, CloudMarketBatchPayload, CloudMarketBatchTarget, CloudMarketResponse, CloudMarketScreenerCategory, CloudMarketScreenerPayload, CloudNewsListResponse, CloudNewsPayload, CloudSavedSearch, CloudSavedSearchInput, CloudSavedSearchListResponse, CloudSearchDocType, CloudSearchDocument, CloudSearchDocumentResponse, CloudSearchHit, CloudSearchResponse, CloudSecContentResponse, CloudSecDocumentsResponse, CloudSecFilingsResponse, CloudOptionsChainPayload, CloudPricePointPayload, CloudQuotePayload, CloudTweetSearchResponse, CloudWorldVenueMapPayload, CloudYieldPointPayload, ScannerFlowHistoryPage, } from "./types"; type CloudApiRequest = (path: string, options?: RequestInit) => Promise; export class CloudDataApi { constructor(private readonly request: CloudApiRequest) {} private requestMarketSymbol( path: string, symbol: string, exchange?: string, ): Promise> { return this.request>( cloudMarketSymbolPath(path, symbol, exchange), ); } private postMarketBatch( path: string, targets: CloudMarketBatchTarget[], mode: "cache-first" | "refresh", ): Promise>> { return this.request>>(path, { method: "POST", body: JSON.stringify({ targets, mode }), }); } /** EQS endpoints live in the plugin client; one prefix-scoped method keeps the shared client small. */ equityScreener(path: string, init?: RequestInit) { return this.request(`/cloud/equity-screener/${path}`, init); } /** Stored implied volatility (HIVG, VCA, OVDV dates); one prefix-scoped method, like EQS. */ impliedVolatility(path: string, init?: RequestInit) { return this.request(`/cloud/iv/${path}`, init); } async searchInstruments( query: string, limit = 10, ): Promise { const response = await this.request< CloudMarketResponse >(cloudMarketSearchPath(query, limit)); return response.data ?? []; } async getCloudEstimateRevisions(symbol: string, exchange: string): Promise { return this.request(`/cloud/research/estimates/${encodeURIComponent(symbol)}?exchange=${encodeURIComponent(exchange)}`, { signal: AbortSignal.timeout(45_000) }); } async getCloudQuote( symbol: string, exchange?: string, ): Promise> { return this.requestMarketSymbol("/market/quote", symbol, exchange); } async getCloudQuotesBatch( targets: CloudMarketBatchTarget[], mode: "cache-first" | "refresh" = "cache-first", ): Promise>> { return this.postMarketBatch("/market/quotes/batch", targets, mode); } async getCloudWorldVenues(): Promise< CloudMarketResponse > { return this.request>( "/market/venues", ); } async getCloudMarketScreener( category: CloudMarketScreenerCategory, count = 25, mode: "cache-first" | "refresh" = "cache-first", ): Promise> { const requestedCount = Number.isFinite(count) ? Math.round(count) : 25; const params = new URLSearchParams({ category, count: String(Math.max(1, Math.min(50, requestedCount))), mode, }); return this.request>( `/market/screener?${params.toString()}`, ); } async getCloudOptionsChain( symbol: string, exchange?: string, expirationDate?: number, ): Promise> { return this.request>( cloudOptionsChainPath(symbol, exchange, expirationDate), ); } async getCloudProfile( symbol: string, exchange?: string, ): Promise> { return this.requestMarketSymbol("/market/profile", symbol, exchange); } async getCloudFundamentals( symbol: string, exchange?: string, ): Promise> { return this.requestMarketSymbol("/market/fundamentals", symbol, exchange); } async getCloudFinancials( symbol: string, exchange?: string, statementHistory?: "extended", ): Promise> { const path = cloudMarketSymbolPath("/market/financials", symbol, exchange); return this.request(statementHistory === "extended" ? `${path}&statementHistory=extended` : path); } async getCloudFinancialsBatch( targets: CloudMarketBatchTarget[], mode: "cache-first" | "refresh" = "cache-first", ): Promise>> { return this.postMarketBatch("/market/financials/batch", targets, mode); } async getCloudHolders( symbol: string, exchange?: string, ): Promise> { return this.requestMarketSymbol("/market/holders", symbol, exchange); } async getCloudAnalystResearch( symbol: string, exchange?: string, ): Promise> { return this.requestMarketSymbol("/market/analyst", symbol, exchange); } async getCloudShortInterest( symbol: string, years?: number, ): Promise> { const params = new URLSearchParams({ symbol: symbol.toUpperCase() }); if (years != null) params.set("years", String(years)); return this.request>( `/market/short-interest?${params}`, ); } async getCloudCorporateActions( symbol: string, exchange?: string, ): Promise> { return this.requestMarketSymbol( "/market/corporate-actions", symbol, exchange, ); } async getCloudStatements( symbol: string, exchange?: string, period: "annual" | "quarterly" | "both" = "both", ): Promise< CloudMarketResponse< Pick > > { return this.request< CloudMarketResponse< Pick > >(cloudStatementsPath(symbol, exchange, period)); } async getCloudHistory( symbol: string, exchange: string, params: CloudHistoryParams = {}, ): Promise> { return this.request>( cloudHistoryPath(symbol, exchange, params), ); } async getCloudExchangeRate( fromCurrency: string, ): Promise & { rate: number }>> { return this.request & { rate: number }>>( cloudExchangeRatePath(fromCurrency), ); } /** * On-demand single-company evidence review. This is a cloud product endpoint, * not a market-data capability, so it is called directly instead of routed * through the asset-data provider. */ async getCloudEquityDiagnostic( symbol: string, exchange?: string, mode: CloudEquityDiagnosticMode = "cache-first", ): Promise { return this.request( "/research/equity-diagnostic", { method: "POST", body: JSON.stringify({ symbol: symbol.trim().toUpperCase(), ...(exchange ? { exchange } : {}), mode, }), }, ); } async getCloudEconomicCalendar(): Promise { return this.request("/cloud/econ/calendar"); } async getCloudFredSeries( seriesId: string, params: CloudFredSeriesParams = {}, ): Promise { return this.request( cloudFredSeriesPath(seriesId, params), ); } async getCloudShiller(): Promise { return this.request(cloudShillerPath()); } async getCloudCotBoard(report: CotFamily, traderClass: CotClass): Promise { return this.request(`/cloud/cot/board?${new URLSearchParams({ report, traderClass })}`); } async getCloudCotContract(code: string, report: CotFamily): Promise { return this.request(`/cloud/cot/contracts/${encodeURIComponent(code)}?${new URLSearchParams({ report })}`); } async getCloudTape(symbol: string, exchange: string, signal?: AbortSignal): Promise { return this.request(`/cloud/tape/${encodeURIComponent(symbol)}?exchange=${encodeURIComponent(exchange)}`, { signal: signal ?? AbortSignal.timeout(30_000) }); } async getCloudYieldCurve(): Promise { return this.request("/cloud/econ/yield-curve"); } async getCloudCryptoMarkets(): Promise { return this.request("/cloud/crypto/markets", { signal: AbortSignal.timeout(45_000) }); } async getCloudCentralBankRates(): Promise { return this.request("/cloud/econ/central-bank-rates", { signal: AbortSignal.timeout(45_000) }); } /** Recorded FLOW prints older than the live tape (Pro); the plugin builds `search`. */ getScannerFlowHistory(search: string, signal?: AbortSignal) { return this.request(`/market/scanner/flow/history?${search}`, { signal }); } getMobileAlertHistory(offset = 0) { return this.request(`/mobile/alerts/history?offset=${offset}`); } async getCloudMoneyMarkets(): Promise { return this.request("/cloud/econ/money-markets", { signal: AbortSignal.timeout(45_000) }); } async getCloudDebtMaturities(symbol: string): Promise { const params = new URLSearchParams({ symbol }); return this.request(`/cloud/debt-maturities?${params}`, { signal: AbortSignal.timeout(45_000) }); } async getCloudShortVolume(symbol: string, scope: ShortVolumeScope = "nms"): Promise { const params = new URLSearchParams({ symbol, scope }); return this.request(`/cloud/short-volume?${params}`, { signal: AbortSignal.timeout(20_000) }); } async getCloudFuturesCurve(root: string): Promise { return this.request(`/cloud/futures/curve/${encodeURIComponent(root)}`, { signal: AbortSignal.timeout(60_000) }); } async getCloudRatePath(): Promise { return this.request("/cloud/econ/rate-path", { signal: AbortSignal.timeout(45_000) }); } async getCloudCds(params: CloudCdsParams = {}): Promise { return this.request(cloudCdsPath(params)); } async getCloudCongressHouse( params: CloudCongressHouseParams = {}, options?: { signal?: AbortSignal }, ): Promise { return this.request( cloudCongressHousePath(params), options, ); } async getCloudJobs(ticker: string, name?: string | null): Promise { return this.request(cloudJobsPath(ticker, name)); } async getCloudJobsPostings( ticker: string, params: CloudJobsPostingsParams = {}, ): Promise { return this.request(cloudJobsPostingsPath(ticker, params)); } async getCloudJobsMovers(limit?: number, offset?: number): Promise { return this.request(cloudJobsMoversPath(limit, offset)); } async getCloudEarningsCalls( params: CloudEarningsCallsParams = {}, ): Promise { return this.request( cloudEarningsCallsPath(params), ); } async getCloudEarningsTranscript( id: string, ): Promise { return this.request( cloudEarningsTranscriptPath(id), ); } async getProxyStatements( ticker: string, ): Promise { return this.request( publicProxyStatementsPath(ticker), ); } async getProxyStatement( ticker: string, year: number, ): Promise { return this.request( publicProxyStatementPath(ticker, year), ); } async getFilingEvents( ticker: string, limit?: number, ): Promise<{ ticker: string; events: CloudFilingEventPayload[] }> { return this.request<{ ticker: string; events: CloudFilingEventPayload[] }>( publicFilingEventsPath(ticker, limit), ); } async getRiskReports(ticker: string): Promise { return this.request( publicRiskReportsPath(ticker), ); } async getRiskReport( ticker: string, year: number, ): Promise { return this.request( publicRiskReportPath(ticker, year), ); } async getCloudSecFilings( params: CloudSecFilingsParams, ): Promise { return this.request(cloudSecFilingsPath(params)); } async getCloudSecFilingDocuments( params: CloudSecFilingParams, ): Promise { return this.request( cloudSecFilingDocumentsPath(params), ); } async getCloudSecFilingContent( params: CloudSecFilingParams, ): Promise { return this.request( cloudSecFilingContentPath(params), ); } async getCloudSec13F( path: string, params: Record = {}, ): Promise { return this.request(cloudSec13FPath(path, params)); } /** * Cross-document full-text search. Pro-gated: unentitled accounts get a 402, * which the caller turns into the access gate rather than an empty result. */ async searchCloudDocuments( params: CloudSearchParams, options?: { signal?: AbortSignal }, ): Promise { return normalizeSearchResponse( await this.request(cloudSearchPath(params), { signal: options?.signal, }), ); } async getCloudSearchDocument( docType: CloudSearchDocType, sourceId: string, options?: { signal?: AbortSignal }, ): Promise { const response = await this.request( cloudSearchDocumentPath(docType, sourceId), { signal: options?.signal }, ); return response.document; } async getCloudSavedSearches(options?: { signal?: AbortSignal; }): Promise { const response = await this.request( cloudSavedSearchesPath(), { signal: options?.signal, }, ); return response.searches ?? []; } async createCloudSavedSearch( input: CloudSavedSearchInput, ): Promise { return normalizeSavedSearchResponse( await this.request(cloudSavedSearchesPath(), { method: "POST", body: JSON.stringify(input), }), ); } async updateCloudSavedSearch( id: string, update: Partial, ): Promise { return normalizeSavedSearchResponse( await this.request(cloudSavedSearchPath(id), { method: "PATCH", body: JSON.stringify(update), }), ); } async deleteCloudSavedSearch(id: string): Promise { await this.request(cloudSavedSearchPath(id), { method: "DELETE" }); } async getCloudSavedSearchHits( id: string, options?: { signal?: AbortSignal }, ): Promise { return normalizeSavedSearchHits( await this.request(cloudSavedSearchHitsPath(id), { signal: options?.signal, }), ); } async getCloudNews( params: CloudNewsParams = {}, ): Promise { return this.request(cloudNewsPath(params)); } async getCloudNewsStory(storyId: string): Promise { return this.request( `/news/${encodeURIComponent(storyId)}`, ); } async getCloudTickerTweets( params: CloudTickerTweetsParams, ): Promise { const response = await this.request( cloudTickerTweetsPath(params), ); return normalizeTweetSearchResponse(response); } async searchCloudTweets( params: CloudTweetSearchParams, ): Promise { const response = await this.request( cloudTweetSearchPath(params), ); return normalizeTweetSearchResponse(response); } }