{"ok":true,"timestamp":"2026-10-10T12:56:40.608289+00:00","manifest_version":"2.160","server":{"name":"astellr-firm","build":"emergency-2158m-2160-6074ea82","shapes":["ec2","firm"],"default_shape":"ec2"},"auth":{"api_key_header":"X-API-Key","admin_key_header":"X-Admin-Key","idempotency_header":"Idempotency-Key","internal_key_header":"X-Internal-Key","capabilities_auth_required":false},"base_url":"https://firm.tengu.co","groups":{"legacy":{"count":11,"description":"EC2-compat surface (tengu_*)"},"v2":{"count":13,"description":"Astellr-FIRM upgrades (tengu_v2_*)"},"v3":{"count":359,"description":"Expert surface: agents, decision, execution, strategies, memory, lab (tengu_v3_*)"},"copilot":{"count":19,"description":"Chat-copilot aggregations (tengu_copilot_*)"},"ml":{"count":5,"description":"Direct ML model surface (tengu_ml_*)"},"admin":{"count":0,"description":"Mutating — requires X-Admin-Key"}},"tools":[{"name":"tengu_snapshot","method":"GET","path":"/api/snapshot/{ticker}","group":"legacy","description":"Live price snapshot for one ticker: latest price plus basic trading stats. Call it when the user asks 'where is X trading right now?' or needs a current quote before any single-name analysis. quote.volume is today's session only: null when the vendor's day bar is an earlier session's (before 04:00 ET, on a closed day, or before the ticker's first trade today). quote.change is price minus prev_close and quote.as_of_ts the last-trade time, the same as /api/market/quote. Heavy endpoint — fetch one ticker per call. Bills to quant_signals (Starter+), not Free. fundamentals: pe_ratio = price / TTM diluted EPS on today's share basis, pb_ratio = price / latest quarter book value per share, market_cap = price x market_cap_shares, the shares outstanding on the latest SEC cover page (unvested restricted stock included), else the reference count, else the latest balance sheet's, else the latest quarter's weighted-average basic count (market_cap_shares_basis says which and market_cap_shares_as_of when; market_cap_basis says so in words, or that it fell back to the prior close), the same count as fundamentals_price_snapshot; market_cap_shares_status says when it is provisional; forward_pe, ev_to_ebitda, dividend_yield and beta are null here (use fundamentals_price_snapshot); null_reasons and fundamentals_status say why. sector is an SIC division (sector_taxonomy). quote.as_of (ISO 8601 UTC), quote.price_age_seconds and quote.is_stale label the last trade (the same 6 hour rule as /api/v3/fundamentals/price_snapshot). A missing time is stale. The price is still returned.","path_params":["ticker"],"admin":false,"replaced_by":"tengu_v3_fundamentals_full","display_name":"Price snapshot (live)","capability_tags":["heavy"],"public_name":"quote_and_fundamentals","replaced_by_public_name":"fundamentals_full"},{"name":"tengu_insider_clusters","method":"GET","path":"/api/insider/clusters","group":"legacy","description":"Clusters of insider buying across companies: tickers where two or more distinct insiders made purchases (Form 4 code P) in the last 30 days. Call it when the user asks 'where are insiders buying?' or wants market-wide insider conviction rather than one company's filings. Each cluster's as_of_ts is its latest purchase date; complete=false would mean the 30-day scan hit its row cap. Clusters computed from the insider feed also carry n_purchases, n_purchases_priced and total_shares: a purchase re-carried by a later ingest or restated in a later filing (a Form 4/A) counts once. Three or more buyers filled on one day at one identical price are one execution on their behalf (an employee purchase plan, a compensation program or an offering), not separate decisions: n_buyers_same_day_price counts them, cluster_score (n_buyers_discretionary / 5, capped at 1) counts only buyers with a purchase of their own, and plan_purchase=true marks a cluster that is mostly such an execution; plan clusters rank after every discretionary one. total_value_usd is shares times the price as filed, served only for a US-incorporated issuer, or a US line that is not an ADR of an issuer with no traded common listing in Canada (a foreign-incorporated US-only listing files in dollars), and only when every purchase is priced. The reference covers US and Canadian lines only, so a home listing outside North America (London, say) is not seen and such an issuer's total is still served as USD, even where a trade was filed at the home-market price; otherwise it is null and total_value_usd_reason says why: adr_home_market_shares (an ADR's filings report the home-market shares, priced in the home currency, and total_shares counts those shares, not ADRs), foreign_issuer_currency_unknown (a foreign issuer with a listing in Canada), issuer_not_identified, issuer_reference_unavailable or unpriced_purchases. No exchange rate is applied. A 503 dataset_unavailable (refunded) means the feed could not be read, not that nobody bought.","admin":false,"query_params":[{"name":"limit","type":"int","default":25,"min":1,"max":500,"description":"Maximum clusters returned."}],"public_name":"insider_clusters"},{"name":"tengu_crypto_universe","method":"GET","path":"/api/crypto/universe","group":"legacy","description":"The full liquid crypto universe: every priced USD pair that clears a dollar-volume floor (default $1M a day), ranked by dollar volume, stablecoins excluded. Both use the last complete UTC day (dollar_volume_24h; dollar_volume_basis says which window, and a pair with no previous day uses today so far; dollar_volume_utc_day_to_date is today so far). Row change_pct_24h is the change since 00:00 UTC, also served as change_pct_utc_day (change_basis); a rolling 24h change for one pair is on the quote tool. The floor is the only cap; nothing is cut to a top-N. Optional limit/offset page through the same book (has_more / next_offset) without hiding names. Counts: priced, excluded_stable, below_floor, returned. GET /api/crypto/sitting is a scored ordering of this book and GET /api/crypto/overnight a mover slice of it. A liquidity ranking, not conviction: not a forecast or a trade signal. Auth: X-API-Key.","query_params":[{"name":"limit","type":"int","min":1,"max":1000,"description":"Optional page size. Omit to return EVERY pair that clears the floor. Pagination, not a universe cap."},{"name":"offset","type":"int","default":0,"min":0,"description":"Offset into the ranked liquid book"},{"name":"min_dollar_volume","type":"float","default":1000000.0,"description":"Minimum dollar volume over the last complete UTC day for a pair to count as tradeable"},{"name":"asset_class","type":"string","default":"crypto","enum":["crypto"],"description":"This route is crypto-native. asset_class=crypto is accepted."}],"admin":false,"display_name":"Full liquid crypto universe","public_name":"crypto_universe"},{"name":"tengu_crypto_sitting","method":"GET","path":"/api/crypto/sitting","group":"legacy","description":"A ranked sleeve of the liquid USD crypto book. Every liquid name in GET /api/crypto/universe (stablecoins out, $1M 24h floor; the full book, not a pre-cut list) is ranked on attached data: multi-horizon momentum (1h/4h/1d/7d from the snapshot and daily bars; a missing horizon is skipped, never zero-filled), volume, and optional news sentiment and event shocks. Funding, open interest and basis are not part of this book. Missing or stale inputs are stated on the row; the name stays and no number is invented. Returns the top N (sleeve_n, default 20; also published as `rows`); the full book stays on /api/crypto/universe. Every row carries blendedScore, decile (decile_convention=10_is_best), as_of and the four signal-bundle keys or explicit nulls. ranked_count is the size of the full ranked book, not the sleeve. The ranking is a scored ordering (signal_quality_mode=ordering_only, edge=no_measurable_edge, not_a_forecast=true), not a forecast; do_not_place_from_mover_rank and do_not_place_from_score are always true and crypto_available is false. Auth: X-API-Key.","query_params":[{"name":"sleeve_n","type":"int","default":20,"min":1,"max":100,"description":"Bounded top-N from the full-book rank"},{"name":"min_dollar_volume","type":"float","default":1000000.0,"description":"Minimum 24h dollar volume for a pair to enter the liquid book"},{"name":"asset_class","type":"string","default":"crypto","enum":["crypto"],"description":"This route is crypto-native. asset_class=crypto is accepted."}],"admin":false,"display_name":"Crypto sitting book","public_name":"crypto_sitting"},{"name":"tengu_equity_sitting","method":"GET","path":"/api/equity/sitting","group":"legacy","description":"A ranked sleeve of the tradeable US equity book. It scans every name in the live feature store (a measured count, not a fixed list), ranks them on attached data (technical, options_flow, news, sentiment; missing or stale inputs are stated on the row, the name stays and no number is invented) and returns the top N (sleeve_n, default 20). The technical lane is 12-1 momentum for every row, never mixed with one-day returns; a 12-1 momentum past +1,000% is flagged implausible_12_1_momentum (typically a price history spliced across a reused ticker) and not ranked. data_order is the mean of the row's lanes, each ranked across the book as a percentile first (fields.percentile). Every sleeve row carries the four signal-bundle keys or explicit nulls. The ranking is an ordering with attached data, not a score or forecast (edge=no_measurable_edge); do_not_place_from_mover_rank is always true. A warm or last-good book is served in milliseconds; the 300s TTL does not evict the last ranked sleeve. Auth: X-API-Key.","query_params":[{"name":"sleeve_n","type":"int","default":20,"min":1,"max":100,"description":"Bounded top-N from the full-book rank"},{"name":"min_adv_dollars","type":"float","default":5000000.0,"description":"ADV floor (default $5M/day — same long-side floor as universe_scan)"},{"name":"min_price","type":"float","default":5.0,"description":"Price floor (default $5, no pennies)"}],"admin":false,"display_name":"US equity sitting book","capability_tags":["heavy"],"public_name":"equity_sitting"},{"name":"tengu_crypto_overnight","method":"GET","path":"/api/crypto/overnight","group":"legacy","description":"Overnight crypto movers: a slice of GET /api/crypto/universe (the liquid USD book, stablecoins out, $1M floor) ordered by the absolute change since 00:00 UTC (change_pct_24h, change_basis; not a rolling 24 hours: change_window says how long the window is, minutes just after midnight). The default 25 movers are a slice, not the full book. Bare symbols (BTC, not BTC-USD), volume (volume_24h and dollar_volume_24h cover the last complete UTC day, volume_basis), as_of, optional sentiment and whale flags. Every row is kind=data_context, not a score or prediction: no crypto model is behind it, and crypto_available is false. When the snapshot book is stale the route answers 503 (ok:false, placement.fail_closed=true, X-Error-Code). /score, /intel/ml_prediction and /execution/* answer 404 crypto_model_unavailable for asset_class=crypto; equity ADV does not size a coin. Tickers here are the coins, never the US-listed equities with the same symbol. Auth: X-API-Key.","query_params":[{"name":"limit","type":"int","default":25,"min":1,"max":100,"description":"How many liquid movers to return"},{"name":"min_dollar_volume","type":"float","default":1000000.0,"description":"Minimum 24h dollar volume for a pair to enter the DATA universe"},{"name":"asset_class","type":"string","default":"crypto","enum":["crypto"],"description":"This route is crypto-native. asset_class=crypto is accepted. Fail-closed 503 (ok:false, placement.fail_closed=true) when the snapshot book is stale."}],"admin":false,"display_name":"Overnight crypto DATA","public_name":"crypto_overnight"},{"name":"tengu_crypto","method":"GET","path":"/api/crypto/{ticker}","group":"legacy","description":"Live crypto quote from the market-data feed (real-time entitlement): last-trade price, change and volume over the last 24 hours (rolling, from one-minute bars; null with rolling_24h_reason when those cannot be read), the since-00:00-UTC change/volume as change_pct_utc_day / volume_utc_day, volumes in the base asset (volume_unit), day + prev-day OHLC, optional last-7 daily bars, honest as_of. as_of, price_age_seconds and is_stale label the last trade. is_stale is true when it is more than 15 minutes old (the same window as /api/v3/fundamentals/price_snapshot?asset_class=crypto) or the time is missing. The price is still returned. PRIMARY tool for 'what is BTC at?'. Accepts BTC/BTCUSD/X:BTCUSD plus a vs currency (e.g. EUR); unknown symbols return a structured 404.","path_params":["ticker"],"query_params":[{"name":"vs","type":"string","default":"USD","description":"Quote currency (e.g. EUR, BTC)"},{"name":"series","type":"bool","default":true,"description":"Include last-7 daily bars"},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional: this tool serves crypto only, so crypto is the one value."}],"admin":false,"display_name":"Crypto markets","public_name":"crypto_quote"},{"name":"tengu_macro","method":"GET","path":"/api/macro","group":"legacy","description":"One-call macro dashboard. Call it FIRST for any 'how is the overall market / macro backdrop?' question, or to frame a single-name view against market conditions. Fields, each with its *_obs_date: vix and vvix (session closes), tnx_10y (10-year Treasury yield, %), yield_curve_10y2y (points), credit_spread (US high-yield option-adjusted spread, %), usd_index_broad (broad trade-weighted dollar); 'units' names each unit. 'releases' holds the latest official CPI, core CPI, PCE and core PCE price indexes, unemployment rate, nonfarm payrolls, real GDP growth and the fed funds target range and effective rate, each with reference_period, released date and 1-month/12-month changes in explicit units. 'regime' is a rule-based classification (regime_method), not a forecast. dxy, sp500_trend and fear_greed are null with a *_reason: the narrow DXY, index levels and live quotes are in tengu_v3_intel_macro_snapshot. Any null carries a *_reason.","admin":false,"public_name":"macro_dashboard"},{"name":"tengu_regime","method":"GET","path":"/api/regime","group":"legacy","description":"Current market regime label plus the model's regime probabilities. Call it when the user asks 'what regime are we in?' or before positioning advice that depends on the prevailing regime; use tengu_v2_regime_forecast for the forward view and tengu_v2_regime_history for the past.","admin":false,"public_name":"market_regime"},{"name":"tengu_status","method":"GET","path":"/api/status","group":"legacy","description":"Prediction-book status: whether the ML prediction book is current (status is green only for a servable book at most 2 sessions old), its newest prediction time, model readiness and retrain metrics. It covers the prediction book only, not market data, live streams or the data archives: for live market data call tengu_v3_stream_status.","admin":false,"public_name":"status"},{"name":"tengu_ready","method":"GET","path":"/api/ready","group":"legacy","description":"Prediction-book readiness: ready is true only when the ML prediction book is servable and at most 2 sessions old; reason says why not. It covers the prediction book only, not market data, live streams or the data archives: for live market data call tengu_v3_stream_status.","admin":false,"public_name":"ready"},{"name":"tengu_v2_multi_horizon_batch","method":"GET","path":"/api/v2/predict/multi_horizon","group":"v2","description":"Multi-horizon model ranks for up to 200 tickers in one call. Only the training horizon (1m) carries a leg; every other requested horizon is null, because no forecast was trained for it. Each leg gives direction and percentile (100 = best rank in the scored book, whose ranking includes the funds and ADRs FIRM excludes from serving; not re-ranked after exclusion). While point_estimate_supported is false, predicted_return_pct is null with withheld 'uncalibrated_point_estimate': the number is blended_score*100, a scored ordering, not a forecast. Every requested ticker is in rows or in missing_tickers, never both; a cold snapshot answers 503 snapshot_cold (retry).","query_params":[{"name":"tickers","type":"string","required":true,"description":"CSV, 1..200 symbols"},{"name":"horizons","type":"string","default":"1m,3m,1y","description":"CSV subset of 1d,1w,1m,3m,1y"}],"admin":false,"display_name":"Model scores (batch)","public_name":"multi_horizon_batch"},{"name":"tengu_v2_intervals","method":"GET","path":"/api/v2/predict/{ticker}/intervals","group":"v2","description":"Conformal band around one ticker's SCORE at the requested miscoverage alpha (default 0.1 = 90%). Call it when the user asks 'how confident is the model?' or wants an uncertainty range rather than a point estimate. READ THE HORIZON: the band is calibrated at a 1-DAY horizon (interval_horizon_days=1), so quoting it as a 1-month range understates that risk by roughly sqrt(20) ~ 4.5x. Check interval_horizon_matches_ordering before pairing it with any other horizon. The centre it brackets is blended_score*100, a scored ordering, not a forecast.","path_params":["ticker"],"query_params":[{"name":"alpha","type":"float","default":0.1,"min":0.01,"max":0.5}],"admin":false,"public_name":"prediction_intervals"},{"name":"tengu_v2_drift","method":"GET","path":"/api/v2/models/drift","group":"v2","description":"Feature and prediction drift over a rolling window (default 30 days). Call it when the user asks whether the models are still well calibrated, why predictions look off, or whether model inputs have shifted recently. Served from the daily voter-drift snapshot: `stale: true` (top level and on each row) means the newest prediction it measured is over 80 hours old (a weekend plus the build lag) or undated; `stale_at_build` is the producer's own row verdict.","query_params":[{"name":"window_days","type":"int","default":30,"min":1,"max":365}],"admin":false,"public_name":"model_drift"},{"name":"tengu_v2_feature_importance","method":"GET","path":"/api/v2/features/importance","group":"v2","description":"Top-N feature importances for the prediction models (default top 50, optionally filtered to one model). Call it when the user asks 'what is the model actually looking at?' or which inputs are driving current predictions. Without a published importance table the rows are FF5 factor loadings and voter posterior weights (each row's `kind` says which), each report's as_of in `report_freshness`.","query_params":[{"name":"top_n","type":"int","default":50,"min":1,"max":500},{"name":"model","type":"string"}],"admin":false,"public_name":"feature_importance"},{"name":"tengu_v2_factor_decay","method":"GET","path":"/api/v2/features/decay","group":"v2","description":"IC/IR half-life per factor — how fast each factor's predictive power decays. Call it when the user asks which signals are going stale, how long a factor's edge lasts, or before weighting factors in a strategy. `stale: true` means the underlying drift snapshot's data is over 80 hours old or undated.","admin":false,"public_name":"factor_decay"},{"name":"tengu_v2_regime_forecast","method":"GET","path":"/api/v2/regime/forecast","group":"v2","description":"Forecast regime probabilities N days ahead (default 21-day horizon). Call it when the user asks 'is the regime about to change?' or wants the forward market-state outlook rather than today's label — use tengu_regime for the current read. current_regime is read from the prediction book: current_regime_as_of is the date it describes and `stale: true` means that book is over 2 sessions old, so the forecast starts from a past regime. A 503 upstream_unavailable (Retry-After 5) means the book is still loading on that server; it is refunded.","query_params":[{"name":"horizon_days","type":"int","default":21,"min":1,"max":252}],"admin":false,"public_name":"regime_forecast"},{"name":"tengu_v2_regime_history","method":"GET","path":"/api/v2/regime/history","group":"v2","description":"Historical regime labels over the last N days (default 180). Call it when the user asks how long the current regime has lasted, when the last regime shift happened, or wants past behavior broken out by regime. `days` is calendar days; coverage_end is the last recorded label. `as_of` is that label's date and `stale: true` means it is over 3 days old: a history, not today's regime. When no label falls inside the window it answers 503 dataset_unavailable (not billed) with coverage_end and min_days_with_labels, the shortest `days` that reaches it; it does not mean the regime was unchanged.","query_params":[{"name":"days","type":"int","default":180,"min":1,"max":3650}],"admin":false,"public_name":"regime_history"},{"name":"tengu_v2_signal_correlation","method":"GET","path":"/api/v2/signals/correlation","group":"v2","description":"Correlation matrix across the voter signals feeding the ensemble. Call it when the user asks whether the model's signals are independent or redundant — high pairwise correlation means the vote count overstates conviction.","admin":false,"public_name":"signal_correlation"},{"name":"tengu_v2_short_interest","method":"GET","path":"/api/v2/short-interest/{ticker}","group":"v2","description":"Short interest for one ticker: the latest settled short interest (shares short, average daily volume, days-to-cover) and the last five sessions of off-exchange short volume, split by FINRA reporting facility (finra_*_short_volume); short_volume_ratio is a percent (tengu_v3_intel_off_exchange serves it as short_volume_share, a fraction), and total_volume is off-exchange volume, not the stock's whole volume (see units). Fails-to-deliver are not carried here: /intel/borrow_cost has them (ftd_recent). Call it FIRST for any 'is X heavily shorted / squeeze candidate?' question or before evaluating short-side risk in a position. An unknown symbol is a 404 unknown_ticker; a 503 means the data could not be read, not that none exists.","path_params":["ticker"],"admin":false,"public_name":"short_interest"},{"name":"tengu_v2_alpha_discoveries","method":"GET","path":"/api/v2/research/alpha_discoveries","group":"v2","description":"Mined alpha expressions from the research pipeline, filtered to a minimum information ratio (min_ir, default 0.5) and capped at `limit` (default 25). Call this when the user asks what alpha signals or factor expressions the research engine has actually discovered. While no discoveries table exists it serves the DSR registry's backtest TRIALS instead (source dsr_registry): raw, UNDEFLATED Sharpes filtered by min_ir, not mined expressions; deflate before trusting any one. When the registry holds no trials it answers 503 dataset_unavailable (refunded), not an empty list; an empty list means trials exist but none clears min_ir.","query_params":[{"name":"limit","type":"int","default":25,"min":1,"max":500},{"name":"min_ir","type":"float","default":0.5,"min":-5.0,"max":10.0}],"admin":false,"public_name":"alpha_discoveries"},{"name":"tengu_v2_strategy_evolution","method":"GET","path":"/api/v2/research/strategy_evolution","group":"v2","description":"Strategy genealogy with out-of-sample (OOS) scores — how each evolved strategy variant descends from its parents and how it validated OOS, up to `limit` entries (default 50). Call this when the user asks how strategies were developed, mutated, or which generations survived validation. While no evolution table exists it serves per-family trial counts and best raw Sharpe from the DSR registry instead (source dsr_registry_families; first_ts/last_ts are registration times), or 503 dataset_unavailable (refunded), not an empty list, when the registry holds no trials.","query_params":[{"name":"limit","type":"int","default":50,"min":1,"max":500}],"admin":false,"public_name":"strategy_evolution"},{"name":"tengu_v2_research_datasets","method":"GET","path":"/api/v2/datasets","group":"v2","description":"Discover the 47 research datasets served by the research-dataset reader — equity prices (daily/monthly/delistings/distributions/mutual funds), fundamentals (annual/quarterly/segments/customers/supply-chain), analyst estimates (summary/detail/guidance/price-targets/actuals/recs), implied volatility, securities-finance (full-history CDS + short interest; known issue: that short-interest file's share counts disagree with the exchange-reported short interest, see its note), transcripts/ratings/key-developments, board relationships, forensic-audit filings, syndicated loans, ESG ratings, crowd estimates, TRACE bond trades and Fama-French factors. Call FIRST when unsure of a slug; not_ingested lists any slug awaiting a table (currently empty).","admin":false,"public_name":"research_datasets"},{"name":"tengu_v2_research_read","method":"GET","path":"/api/v2/datasets/{dataset}","group":"v2","description":"Read any research dataset by slug (discover via tengu_v2_research_datasets). ?ticker= pushes an exact server-side filter down the dataset's own symbol column when it has one; datasets keyed by an internal security id instead state explicitly that ticker was ignored. The `implied_vol_by_ticker` slug REQUIRES ?ticker= and resolves the symbol to that id automatically before pushdown. The `cds_composites` slug serves the FULL 2005–2025 spread history. Unfiltered reads are capped at 5000 rows.","path_params":["dataset"],"query_params":[{"name":"ticker","type":"string","description":"exchange symbol — pushed down the dataset's own symbol column"},{"name":"limit","type":"int","default":1000,"min":1,"max":50000},{"name":"permno","type":"int","min":1,"max":9999999,"description":"security number — only on datasets keyed by it (security_names_history, security_issuer_links); 422 elsewhere"},{"name":"gvkey","type":"string","description":"issuer key, 1-6 digits — only on datasets keyed by it (security_issuer_links, fundamentals_pit_report_dates); 422 elsewhere"}],"admin":false,"public_name":"research_read"},{"name":"tengu_v3_agents_list","method":"GET","path":"/api/v3/agents","group":"v3","description":"Catalogue of every agent in the swarm — one entry per agent. Call this when the user asks which agents exist, what the swarm is composed of, or to resolve an agent's name before drilling into its output.","admin":false,"public_name":"agents_list"},{"name":"tengu_v3_trade_setups","method":"GET","path":"/api/v3/decision/trade_setups","group":"v3","description":"Top trade setups from the decision engine with **defensive-alternates baked in**. When the screen is one-sided (>=70% same direction across 3+ picks), the response carries `universe_skew` = 'bearish' | 'bullish' | 'mixed' AND a `regime_warranted_alternative` block containing the editorial fallback basket (defensive | cash_heavy | value_tilt | momentum). Each alternative carries strategy label, curated candidates with thesis per name, and a one-sentence rationale. Use the alternative when the primary picks don't fit the user's risk frame — e.g. all-bearish screen on a long-bias capital-allocation query surfaces the `defensive` basket so the model never has to refuse or invent. The skew counts LONG/SHORT setups only: NEUTRAL setups are unclassified, so a screen of NEUTRAL rows is 'mixed' with no alternative. as_of_ts, book_age_sessions and is_stale give the age of the prediction book the setups come from. Schema is ADDITIVE — primary `setups` array unchanged from v2.41.","query_params":[{"name":"limit","type":"int","default":25,"min":1,"max":500},{"name":"min_conviction","type":"float","default":0.0,"min":0.0,"max":1.0}],"admin":false,"display_name":"Trade screens","public_name":"trade_setups"},{"name":"tengu_v3_universe_scan","method":"GET","path":"/api/v3/decision/universe_scan","group":"v3","description":"Latest universe-scanner output: the most recent scan results across the tradable universe, up to `limit` names (default 100). Call this when the user asks what the scanner is flagging right now or wants a market-wide sweep before drilling into single tickers.","query_params":[{"name":"limit","type":"int","default":100,"min":1,"max":5000},{"name":"min_adv_dollars","type":"float","min":0,"description":"ADV liquidity floor in dollars/day. Default: 5,000,000 for long-signal rows / 10,000,000 for short-signal rows (borrow needed). 0 disables."}],"admin":false,"display_name":"Universe scan","public_name":"universe_scan"},{"name":"tengu_v3_ultimate_decision","method":"GET","path":"/api/v3/decision/ultimate","group":"v3","description":"Ultimate-engine aggregate decision for one ticker — the top-level verdict aggregated across the engine stack. PRIMARY tool for 'so what's the final call on <ticker>?' — call it when the user wants one consolidated decision rather than raw component signals.","query_params":[{"name":"ticker","type":"string"}],"admin":false,"display_name":"Final verdict","capability_tags":["heavy"],"public_name":"ultimate_decision"},{"name":"tengu_v3_twap_plan","method":"GET","path":"/api/v3/execution/twap_plan/{ticker}","group":"v3","description":"Even-slice arithmetic scenario for a requested quantity and duration. Preserves whole shares and the full time window. No liquidity, market-calendar, execution-cost, or fill guarantee.","path_params":["ticker"],"query_params":[{"name":"qty","type":"int","default":100,"min":1,"max":10000000},{"name":"minutes","type":"int","default":60,"min":1,"max":390}],"admin":false,"display_name":"TWAP execution","public_name":"twap_plan"},{"name":"tengu_v3_vwap_plan","method":"GET","path":"/api/v3/execution/vwap_plan/{ticker}","group":"v3","description":"Historical volume-weighted quantity scenario for one ticker and a completed XNYS session. Uses every observed minute of that session; missing or conflicting evidence returns unavailable. Defaults to the last completed session. Not a forecast, cost estimate, or executable order.","path_params":["ticker"],"query_params":[{"name":"qty","type":"int","default":100,"min":1,"max":10000000},{"name":"reference_date","type":"string","description":"Completed session date, YYYY-MM-DD"},{"name":"minutes_per_slice","type":"int","default":30,"min":1,"max":60}],"capability_tags":["heavy"],"admin":false,"display_name":"VWAP execution","public_name":"vwap_plan"},{"name":"tengu_v3_strategies_list","method":"GET","path":"/api/v3/strategies","group":"v3","description":"Catalogue of the 21-strategy library — one entry per strategy. Call this when the user asks which strategies exist or what the system can run, or to resolve a strategy name before drilling into its evolution or signals.","admin":false,"display_name":"Strategy list","public_name":"strategies_list"},{"name":"tengu_v3_signals_fusion","method":"GET","path":"/api/v3/signals/fusion","group":"v3","description":"Latest fused signals across all voters — the combined signal after voter aggregation, up to `limit` names (default 100). Call this when the user asks what the system's current signals are overall; use signals_mtf for one ticker's timeframe alignment.","query_params":[{"name":"limit","type":"int","default":100,"min":1,"max":5000},{"name":"tickers","type":"string","description":"Optional comma-separated tickers (e.g. AAPL,NVDA). When given, returns the fused signal for exactly those names — making fusion a viable bulk lookup, not only a top-N-by-strength feed."}],"admin":false,"display_name":"Combined signals","public_name":"signals_fusion"},{"name":"tengu_v3_signals_mtf","method":"GET","path":"/api/v3/signals/mtf/{ticker}","group":"v3","description":"One EQUITY cross-horizon ensemble row for a ticker. Despite the legacy `mtf` path name, the warehouse does NOT emit independent per-timeframe rows, so this tool cannot confirm 1m/4h/1w agreement and must not be cited as multi-timeframe evidence. predicted_return_pct, interval_lo and interval_hi are null with withheld: 'uncalibrated_point_estimate' (predicted_return_pct is blended_score x 100: a scored ordering, not a forecast); blended_score, conviction, decile and rank are served. Crypto requests fail closed.","path_params":["ticker"],"admin":false,"display_name":"Multi-timeframe read","public_name":"signals_mtf"},{"name":"tengu_v3_signals_veto","method":"GET","path":"/api/v3/signals/veto_state","group":"v3","description":"Active veto state — which risk, regime, or circuit-breaker (CB) vetoes are currently in force over signals. Call it to know whether signals are being suppressed before trusting any signal read; PRIMARY for 'why isn't the system acting on <ticker>?'.","admin":false,"display_name":"Risk filters","public_name":"signals_veto"},{"name":"tengu_v3_signals_cross_asset","method":"GET","path":"/api/v3/signals/cross_asset","group":"v3","description":"Cross-asset regime signals — the regime read taken across asset classes rather than from single tickers. Call this when the user asks about the broader market regime or wants cross-asset confirmation of a single-asset view. A value the source cannot have meant (a 0.0 missing-input marker, a NULL input the builder never read, or a level outside a wide plausibility range) is null, as is every field computed from it; the bucket's invalid_fields says which and why. There is no ICE Dollar Index level: fx.dx_front is always null, usd_proxy_eur_per_usd is 1/EURUSD from the CME euro future, and dxy_momentum is that proxy's direction only.","admin":false,"display_name":"Cross-asset signals","public_name":"signals_cross_asset"},{"name":"tengu_v3_self_healing","method":"GET","path":"/api/v3/monitoring/self_healing","group":"v3","description":"Recent and pending self-healing actions the system has taken or queued. Call when the user asks whether the system/data pipeline is healthy or why data looks missing/stale.","admin":false,"query_params":[{"name":"limit","type":"int","default":100,"description":"Maximum events returned."}],"public_name":"self_healing"},{"name":"tengu_v3_system_health","method":"GET","path":"/api/v3/monitoring/system_health","group":"v3","description":"Aggregate system health with per-subsystem status. Call when the user asks whether the system/data pipeline is healthy or why data looks missing/stale.","query_params":[{"name":"freshness","type":"string","default":"live","enum":["off","live","strict"],"description":"Freshness policy. 'live' (default) and 'strict' return 503 data_stale for a missing or stale snapshot; use 'off' only for diagnostic inspection"}],"admin":false,"public_name":"system_health"},{"name":"tengu_v3_api_quotas","method":"GET","path":"/api/v3/monitoring/api_quotas","group":"v3","description":"External API quota state, as far as this service can observe it (news, news-analytics, market-data, alt-data). Each row states its neutral feed label and counter_scope; most calls to a source are made by other services, so their counters are null with status 'unknown' (not observed), never 0 / OK. A daily budget row states budget_status separately: a budget with room is not a vendor accepting calls, so can_call is null unless this service saw the source refuse (status vendor_refusing). any_at_cap is null unless every counter was observed.","admin":false,"public_name":"api_quotas"},{"name":"tengu_v3_accuracy","method":"GET","path":"/api/v3/learning/accuracy","group":"v3","description":"Realised-vs-predicted accuracy over a rolling window (window_days, default 90) — how well predictions matched what actually happened. Call this when the user asks how accurate the system has been or wants a track record before trusting a new call; use prediction_tracker for individual predictions.","query_params":[{"name":"window_days","type":"int","default":90,"min":1,"max":3650}],"admin":false,"public_name":"prediction_accuracy"},{"name":"tengu_v3_prediction_tracker","method":"GET","path":"/api/v3/learning/prediction_tracker","group":"v3","description":"Recent predictions with their resolution state, up to `limit` entries (default 200) — each call and whether it has resolved yet and how. Call this when the user asks what the system has predicted lately or how specific calls turned out; use accuracy for the aggregate hit-rate.","query_params":[{"name":"limit","type":"int","default":200,"min":1,"max":5000}],"admin":false,"display_name":"Prediction tracking","public_name":"prediction_tracker"},{"name":"tengu_v3_optimizer_latest","method":"GET","path":"/api/v3/optimizer/latest","group":"v3","description":"Ensemble voter weights from the most recent run of each weight job (signal-blending weights, not portfolio allocations): the posterior voter weights and the per-regime vectors. `freshness` gives each set's as_of and age in trading sessions; is_stale / stale_reason say when a set is older than two sessions, i.e. not a current weight set. Call this when the user asks how the ensemble weights its signals.","admin":false,"display_name":"Latest optimizer run","public_name":"optimizer_latest"},{"name":"tengu_v3_news_aggregated","method":"GET","path":"/api/v3/news/aggregated","group":"v3","description":"MARKET-WIDE feed by default: the aggregated cross-source news stream published in the last N hours (default 24), newest first, for broad market-news sweeps. With ticker, the same window holds only the headlines the source tags with that one symbol (the answer echoes ticker, source news_ticker); for the full per-ticker read use tengu_v3_news_summary. No headline for the symbol in the window is an empty list with a note, never the market-wide feed; an unlisted symbol is 404 unknown_ticker. Not de-duplicated: a story carried by several outlets appears once per outlet. At most 150 items are read per request; coverage.complete is false (with a note) when the answer does not reach back the full window.","query_params":[{"name":"hours","type":"int","default":24,"min":1,"max":168},{"name":"limit","type":"int","default":100,"min":1,"max":1000},{"name":"ticker","type":"string","description":"one symbol: only headlines the source tags with it; omit for the market-wide feed"}],"admin":false,"display_name":"News digest","public_name":"news_aggregated"},{"name":"tengu_v3_news_events","method":"GET","path":"/api/v3/news/events","group":"v3","description":"Detected market-moving events across the market over a lookback window (hours param, default 24). Call this when the user asks 'did anything big happen today?' or wants a scan of recent catalysts market-wide; use tengu_v3_news_latest for headlines on one ticker. An event's date is when the source formed its cluster, which can be hours after the first article.","query_params":[{"name":"hours","type":"int","default":24,"min":1,"max":168}],"admin":false,"display_name":"News events","public_name":"news_events"},{"name":"tengu_v3_thresholds","method":"GET","path":"/api/v3/experience/thresholds","group":"v3","description":"Currently-active decision thresholds — the live cutoff values gating automated trade decisions right now. Call it to know which thresholds are in force before interpreting why a signal did or didn't become a decision.","admin":false,"public_name":"thresholds"},{"name":"tengu_v3_hedging","method":"GET","path":"/api/v3/institutional/hedging","group":"v3","description":"Index hedge proposals (SPY/QQQ/IWM) computed from live dealer positioning — protective puts when dealers are short gamma and IV rank is cheap, plus an IV term-structure note when front-week IV is at least 5% above 30-day IV. No collar is proposed: 'withheld_rules' says why. 'units' says what each metric is measured in","admin":false,"display_name":"Hedge analysis","public_name":"index_hedge_proposals"},{"name":"tengu_v3_cpcv","method":"POST","path":"/api/v3/validation/cpcv","group":"v3","description":"Subsample Sharpe dispersion over the combinatorial group splits of CPCV (AFML Ch. 12) on a return series you POST: the series is cut into n_groups time blocks and the Sharpe of every k-block subset is reported (n_splits = C(n_groups, k); n_paths = AFML's backtest-path count, k/n_groups x C(n_groups, k)). Nothing is refit, so it is NOT an out-of-sample test and cannot detect overfitting or selection bias: a series picked as the best of many backtests scores about its in-sample Sharpe here too. Call it when the user asks how stable a return series' Sharpe is across time; to ask whether a Sharpe is real or a multiple-testing artifact, use tengu_v3_deflated_sharpe with the number of trials.","body_schema":{"required":["returns"],"type":"object","properties":{"returns":{"items":{"type":"number"},"maxItems":20000,"minItems":1,"type":"array","description":"flat per-period return series, at least max(3 x n_groups, 100) returns"},"n_groups":{"default":10,"maximum":20,"minimum":3,"type":"integer","description":"time blocks the series is cut into"},"embargo_days":{"default":5,"minimum":0,"type":"integer","description":"returns dropped at the start of each block; below the block size, len(returns) // n_groups"},"k":{"default":2,"maximum":19,"minimum":2,"type":"integer","description":"blocks per subset, at most n_groups - 1; C(n_groups, k), the subsets scored, may be at most 2,000 per call"},"annualisation":{"default":252.0,"exclusiveMinimum":0,"maximum":525600,"type":"number","description":"periods per year of the returns (252 daily, 52 weekly, 12 monthly)"}},"additionalProperties":false},"admin":false,"display_name":"CPCV validation","public_name":"cpcv"},{"name":"tengu_v3_deflated_sharpe","method":"POST","path":"/api/v3/validation/deflated_sharpe","group":"v3","description":"Deflated Sharpe Ratio (AFML Ch.11) from an observed Sharpe given the number of trials, observations, and higher moments you supply. Call it when the user asks 'is this Sharpe real or a multiple-testing artifact?'; use tengu_v3_deflate to source the trial count from the registry instead. The Sharpe is read as annualised over periods_per_year (default 252, so n_obs counts days); expected_max_sr, std_sr and deflated_alpha_sr come back on the same scale (units block).","body_schema":{"required":["sharpe"],"type":"object","properties":{"sharpe":{"maximum":1000.0,"minimum":-1000.0,"type":"number","description":"the observed annualised Sharpe (pass periods_per_year 1 for a per-period Sharpe)"},"n_trials":{"default":1,"maximum":1000000000000,"minimum":1,"type":"integer"},"n_obs":{"default":252,"maximum":1000000000000,"minimum":30,"type":"integer","description":"number of return periods the Sharpe was measured on"},"skewness":{"default":0.0,"maximum":1000.0,"minimum":-1000.0,"type":"number"},"kurtosis":{"default":3.0,"maximum":1000000.0,"minimum":1.0,"type":"number","description":"raw (Pearson) kurtosis of the per-period returns: a normal distribution is 3.0; excess kurtosis (pandas .kurt(), scipy's default) is 3 lower. Every distribution has kurtosis >= skewness^2 + 1; moments that break it can make the Sharpe estimator's variance negative, which is refused (422 moments_inconsistent)"},"periods_per_year":{"default":252.0,"maximum":525600,"minimum":1.0,"type":"number","description":"periods per year of the returns behind sharpe and n_obs (252 daily, 52 weekly, 12 monthly); 1 if sharpe is per-period"}},"additionalProperties":false},"admin":false,"display_name":"Deflated Sharpe","public_name":"deflated_sharpe"},{"name":"tengu_v3_deflate","method":"POST","path":"/api/v3/validation/deflate","group":"v3","description":"Deflates a supplied Sharpe ratio using the registry's lifetime trial count — no need to pass trials yourself. Call this for a multiple-testing-honest Sharpe on work tracked by this system; use tengu_v3_deflated_sharpe when you have your own trials and moments. Refuses rather than deflating against a count it does not have: 503 dataset_unavailable (refunded) when the registry holds no trials, 409 insufficient_trials when the family has none (pass n_trials_override, >= 1). The registered count is a FLOOR on trials actually run; the registry block names the corpus publication it came from (corpus) and the archived earlier research-loop cycles merged behind it (archive), each trial counted once. The Sharpe is read as annualised over periods_per_year (default 252).","body_schema":{"required":["strategy_family","sharpe"],"type":"object","properties":{"strategy_family":{"minLength":1,"type":"string","description":"registry family key whose lifetime trial count deflates the Sharpe"},"sharpe":{"maximum":1000.0,"minimum":-1000.0,"type":"number","description":"the observed annualised Sharpe (pass periods_per_year 1 for a per-period Sharpe)"},"n_obs":{"default":252,"maximum":1000000000000,"minimum":30,"type":"integer","description":"number of return periods the Sharpe was measured on"},"skewness":{"default":0.0,"maximum":1000.0,"minimum":-1000.0,"type":"number"},"kurtosis":{"default":3.0,"maximum":1000000.0,"minimum":1.0,"type":"number","description":"raw (Pearson) kurtosis of the per-period returns: a normal distribution is 3.0; excess kurtosis (pandas .kurt(), scipy's default) is 3 lower. Every distribution has kurtosis >= skewness^2 + 1; moments that break it can make the Sharpe estimator's variance negative, which is refused (422 moments_inconsistent)"},"periods_per_year":{"default":252.0,"maximum":525600,"minimum":1.0,"type":"number","description":"periods per year of the returns behind sharpe and n_obs (252 daily, 52 weekly, 12 monthly); 1 if sharpe is per-period"},"n_trials_override":{"maximum":1000000000000,"minimum":1,"type":["integer","null"],"description":"bypass the registry count"}},"additionalProperties":false},"admin":false,"public_name":"deflate"},{"name":"tengu_v3_validation_trials","method":"GET","path":"/api/v3/validation/trials","group":"v3","description":"Recent trials recorded in the DSR registry (limit param, default 100). Call it when the user asks what backtests or experiments have been run, or to audit the multiple-testing history behind a deflated Sharpe. Lists REGISTERED trials only; 503 dataset_unavailable (refunded), not an empty list, when the registry holds none.","query_params":[{"name":"strategy_family","type":"string","description":"only this registry family"},{"name":"limit","type":"int","default":100,"min":1,"max":1000}],"admin":false,"display_name":"Validation trials","public_name":"validation_trials"},{"name":"tengu_v3_validation_trial_count","method":"GET","path":"/api/v3/validation/trial_count","group":"v3","description":"Lifetime count of registered trials — the N used for DSR deflation, and a FLOOR on the trials actually run (unregistered experiments are invisible to it). Call it to know how heavy the multiple-testing burden is before interpreting any deflated Sharpe, or when the user asks how many strategy variants have been tried. 503 dataset_unavailable (refunded), never 0, when the registry holds no trials. `since` filters on submitted_at, the REGISTRATION time, not when a trial ran (since_basis, registry.submitted_at_basis).","query_params":[{"name":"strategy_family","type":"string","description":"count only this registry family"},{"name":"since","type":"string","description":"ISO-8601 lower bound on submitted_at (registration time)"}],"admin":false,"public_name":"validation_trial_count"},{"name":"tengu_v3_kelly_uncertainty","method":"GET","path":"/api/v3/validation/{ticker}/kelly_uncertainty","group":"v3","description":"Uncertainty-discounted Kelly fraction for one ticker — the bet size after haircutting full Kelly for estimation error, computed in DECIMAL units and capped at 25%. Call this when the user asks 'how much should I bet on X?'. It is often WITHHELD: kelly_fraction null with warning / withheld_reasons (book_stale when the scored book is more than two sessions old, magnitude_unsupported when the live measurement does not support a magnitude, or a missing input). Its mu is predicted_return_pct = blended_score*100, a scored ordering, not a forecast, which is why the size is gated. A withheld size is a refusal: say so, do not substitute a size of your own. as_of_ts and book_age_sessions give the book's age.","path_params":["ticker"],"admin":false,"display_name":"Position sizing","public_name":"kelly_uncertainty"},{"name":"tengu_v3_stream_ticks","method":"GET","path":"/api/v3/stream/ticks","group":"v3","description":"SSE stream of live US-equity trades. A filtered connect queues cross-process T+Q coverage; the dedicated producer reconciles it asynchronously (target ~5s). size is shares, fractional for a fractional-share print (null with size_reason when that print's size did not arrive). as_of repeats timestamp, the trade time.","query_params":[{"name":"symbols","type":"string","description":"Comma-separated ticker filter"}],"admin":false,"capability_tags":["chat_excluded","sse"],"public_name":"stream_ticks"},{"name":"tengu_v3_stream_bars","method":"GET","path":"/api/v3/stream/bars","group":"v3","description":"SSE stream of live 1-minute OHLCV bars for EVERY US-listed ticker (no subscribe step needed — the all-ticker feed is always on). Each frame closes one 1-minute candle a few seconds after the minute ends: open/high/low/close/volume/vwap + bar_period_s=60 + bar_start/bar_end. timestamp is the bar's END (= bar_end); tape bars and charts label the same bar by its START (bar_start = timestamp - 60 s). The live-candle feed for charting; quiet outside ~04:00-20:00 ET, which is correct. For chart HISTORY use REST aggregates, not a stream. as_of repeats timestamp, the bar end.","query_params":[{"name":"symbols","type":"string","description":"Comma-separated ticker filter (optional)"}],"admin":false,"capability_tags":["chat_excluded","sse"],"public_name":"stream_bars"},{"name":"tengu_v3_stream_quotes","method":"GET","path":"/api/v3/stream/quotes","group":"v3","description":"SSE stream of live per-venue bid/ask quote events for the requested symbols (bid/ask price+size + per-side venue IDs). Connecting auto-subscribes coverage within ~5s. Quiet outside US market hours — that is correct, not broken. bid_size and ask_size are share counts at the quoting venue (size_unit 'shares'); the round lot is price-tiered (100 shares at $250 or less, 40 to $1,000, 10 to $10,000, 1 above) and not in the frame. as_of repeats timestamp, the quote time.","query_params":[{"name":"symbols","type":"string","required":true,"description":"Comma-separated tickers (required)"}],"admin":false,"capability_tags":["chat_excluded","sse"],"public_name":"stream_quotes"},{"name":"tengu_v3_stream_quotes_subscribe","method":"POST","path":"/api/v3/stream/quotes/subscribe","group":"v3","description":"Pre-warm live-quote coverage for up to 50 symbols before opening the quotes SSE (idempotent; extends the TTL). Use when a consumer wants first-frame data instead of paying the ~5s subscribe latency on connect. Redis outage or a fully occupied 200-symbol shared warm budget returns retryable 503; partial admission is listed explicitly.","body_schema":{"type":"object","required":["symbols"],"properties":{"symbols":{"type":"array","maxItems":50,"items":{"type":"string"}},"ttl_s":{"type":"number","minimum":30,"maximum":3600,"default":300}}},"admin":false,"public_name":"tengu_v3_stream_quotes_subscribe"},{"name":"tengu_v3_stream_signals","method":"GET","path":"/api/v3/stream/signals","group":"v3","description":"SSE stream of fused signals. While the signal producer is not running the connect answers 503 upstream_unavailable (error_code producer_unavailable) instead of an empty stream. ready=true is the transport only; the ready frame's producer_live / producers say whether the signal producer is running.","query_params":[{"name":"symbols","type":"string"}],"admin":false,"capability_tags":["chat_excluded","sse"],"public_name":"stream_signals"},{"name":"tengu_v3_stream_decisions","method":"GET","path":"/api/v3/stream/decisions","group":"v3","description":"SSE stream of decision-lifecycle events. While the decision producer is not running the connect answers 503 upstream_unavailable (error_code producer_unavailable) instead of an empty stream. ready=true is the transport only; the ready frame's producer_live / producers say whether the decision producer is running.","query_params":[{"name":"symbols","type":"string"}],"admin":false,"capability_tags":["chat_excluded","sse"],"public_name":"stream_decisions"},{"name":"tengu_v3_stream_alerts","method":"GET","path":"/api/v3/stream/alerts","group":"v3","description":"UNAVAILABLE: no producer publishes risk or guardrail alerts, so a connect answers 503 upstream_unavailable (error_code producer_unavailable) instead of a heartbeat-only stream. SSE stream of risk / guardrail alerts.","admin":false,"capability_tags":["chat_excluded","sse"],"public_name":"stream_alerts"},{"name":"tengu_v3_stream_news","method":"GET","path":"/api/v3/stream/news","group":"v3","description":"UNAVAILABLE: no news producer publishes the live news stream, so a connect answers 503 upstream_unavailable (error_code producer_unavailable) instead of a heartbeat-only stream; for recent articles use tengu_v3_news_latest. SSE stream of structured-news items.","query_params":[{"name":"symbols","type":"string"}],"admin":false,"capability_tags":["chat_excluded","sse"],"public_name":"stream_news"},{"name":"tengu_v3_stream_events","method":"GET","path":"/api/v3/stream/events","group":"v3","description":"Per-user SSE event stream, scoped to the calling key: a customer key reads only its own namespace, whatever user_id it passes. A call with no authenticated principal returns 403.","query_params":[{"name":"user_id","type":"string","required":true,"server_injected":true}],"admin":false,"capability_tags":["chat_excluded","sse"],"public_name":"stream_events"},{"name":"tengu_v3_stream_market_events","method":"GET","path":"/api/v3/stream/market_events","group":"v3","description":"UNAVAILABLE: no producer publishes market events, so a connect answers 503 upstream_unavailable (error_code producer_unavailable) instead of a heartbeat-only stream that would read as a calm market. SSE stream of freshness-labelled market events. Every record carries source as-of time, feed lag and staleness so old data cannot masquerade as a new breach.","query_params":[{"name":"symbols","type":"string"}],"admin":false,"capability_tags":["chat_excluded","sse"],"public_name":"stream_market_events"},{"name":"tengu_v3_market_events_catchup","method":"GET","path":"/api/v3/events","group":"v3","description":"UNAVAILABLE: the market-event stream has no producer publishing, so there is nothing to catch up from; every call answers 503 dataset_unavailable. Finite catch-up page for retained market events after a stream event id; use after reconnect and preserve each event's source freshness fields. When the stream cannot be read it returns 503 upstream_unavailable (error_code redis_unavailable; not billed), never an empty page; a malformed since is a 422; feed.last_event_age_s is the age of the newest event.","query_params":[{"name":"since","type":"string","description":"Exclusive Redis stream id (<ms> or <ms>-<seq>), or '-' for the start"},{"name":"symbols","type":"string"},{"name":"limit","type":"integer"}],"admin":false,"public_name":"market_events_catchup"},{"name":"tengu_v3_stream_status","method":"GET","path":"/api/v3/stream/status","group":"v3","description":"Bounded Redis reachability plus expiring market-producer and signal-pipeline heartbeats, per-capability readiness, coverage modes/limits and the SSE endpoints that would open now (refused feeds are in unavailable_sse_endpoints). A capability's status is ready, degraded (live=true: publishing with losses named in degraded_reasons), unavailable (nothing publishes; market_data.not_running_reason says why) or unknown (its heartbeat could not be read). Market data is live only while its feed is fresh (a feed message within 90 s of a producer heartbeat at most 120 s old, or a tick, bar or quote within 120 s; outside the 04:00-20:00 ET sessions not_running_reason is outside_session); signals or decisions while their own lane runs, in the dedicated processor's heartbeat or as a generator in the API process itself. Call before claiming live data or diagnosing missing/stale feeds.","admin":false,"public_name":"stream_status"},{"name":"tengu_v3_stream_ingest_status","method":"GET","path":"/api/v3/stream/ingest_status","group":"v3","description":"Live-data ingest status: the dedicated US-equity producer that serves production (dedicated_service: heartbeat, state, degraded_reasons, subscribed symbols, counters; effective_status running / running_degraded / not_running (not_running_reason, e.g. no_vendor_messages or outside_session) / unknown (its heartbeat could not be read)), beside the optional in-process ingest daemon's own fields, which production does not run (disabled_reason served_by_dedicated_service). Call when the user asks why live data looks missing/stale.","admin":false,"public_name":"stream_ingest_status"},{"name":"tengu_v3_stream_signal_generator_status","method":"GET","path":"/api/v3/stream/signal_generator_status","group":"v3","description":"Effective signal-generator status across the optional in-process worker and dedicated processor heartbeat: input ticks, emitted signals and deployment state. effective_status is unavailable when no producer reports, degraded when it reports but does not run. Call when live signals look missing/stale.","admin":false,"public_name":"stream_signal_generator_status"},{"name":"tengu_v3_stream_tick_writer_status","method":"GET","path":"/api/v3/stream/tick_writer_status","group":"v3","description":"Tick writer (tick-persistence buffer) status: buffered rows, batches written, last flush duration. Call when the user asks whether the pipeline is healthy or why stored tick data looks missing.","admin":false,"public_name":"stream_tick_writer_status"},{"name":"tengu_v3_stream_decision_generator_status","method":"GET","path":"/api/v3/stream/decision_generator_status","group":"v3","description":"Effective decision-generator status across the optional in-process worker and dedicated processor heartbeat: input signals, emitted decisions, deployment state and local gate counters. effective_status is unavailable when no producer reports, degraded when it reports but does not run. Call when decisions are missing.","admin":false,"public_name":"stream_decision_generator_status"},{"name":"tengu_v3_stream_news_publisher_status","method":"GET","path":"/api/v3/stream/news_publisher_status","group":"v3","description":"News publisher status: polls completed, articles seen/published, dedup hits, newswire availability. Call when the user asks why news looks missing/stale or whether the pipeline is healthy.","admin":false,"public_name":"stream_news_publisher_status"},{"name":"tengu_v3_stream_universe_status","method":"GET","path":"/api/v3/stream/universe_status","group":"v3","description":"Legacy in-process UniverseManager diagnostics for dev. For production cross-process warm coverage use tengu_v3_market_universe and tengu_v3_stream_status.","admin":false,"public_name":"stream_universe_status"},{"name":"tengu_v3_market_universe","method":"GET","path":"/api/v3/market/universe","group":"v3","description":"Cross-process shared warm-set catalog plus the dedicated US-equity producer heartbeat, research-universe count, capacity and effective readiness. Warm means requested, not provider-confirmed.","admin":false,"public_name":"market_universe"},{"name":"tengu_v3_market_universe_warm","method":"POST","path":"/api/v3/market/universe/warm","group":"v3","description":"Queues expiring cross-process trade+quote coverage (body {\"symbols\": [...]}, up to 200). The dedicated producer reconciles asynchronously on its target ~5s poll; success does not claim provider confirmation. Redis failure or zero admission because the shared budget is full returns a retryable 503; partial admission is explicit.","body_schema":{"type":"object","required":["symbols"],"properties":{"symbols":{"type":"array","items":{"type":"string"},"minItems":1,"maxItems":200}}},"admin":false,"public_name":"tengu_v3_market_universe_warm"},{"name":"tengu_v3_stream_realtime_guide","method":"GET","path":"/api/v3/stream/realtime_guide","group":"v3","description":"Agent protocol for real-time queries: which SSE feed maps to which intent (live price, bars, quotes, signals, decisions, news), payload shapes and units, when to prefer SSE over REST, and fallback rules when a feed is not ready","admin":false,"public_name":"stream_realtime_guide"},{"name":"tengu_v3_news_latest","method":"GET","path":"/api/v3/news/latest","group":"v3","description":"DRILL-DOWN ONLY — never a first-round call and never alongside tengu_v3_news_summary (it already includes recent stories). Raw newswire headlines for one ticker over a lookback window (minutes param, default 60; 60s TTL) for when the summary's stories are insufficient or you need a tighter time window.","query_params":[{"name":"ticker","type":"string","required":true},{"name":"minutes","type":"int","default":60,"min":5,"max":1440}],"admin":false,"display_name":"Latest news","public_name":"news_latest"},{"name":"tengu_v3_news_by_topic","method":"GET","path":"/api/v3/news/by_topic","group":"v3","description":"Topic-filtered headlines, optionally per ticker, over a date_range (default last7days, 50 items). Topics are the news source's own categories: earnings, dividend, layoffs, lawsuit, mergers (M&A), pricemovement, tanalysis, product, ceo, pressrelease, podcast, oil, futures. Call it when the user asks about one of those event types, e.g. 'recent M&A headlines'. There is NO category for ipo, fda, analysts, price targets, guidance, buybacks, splits, bankruptcy, insider, esg or crypto: those answer 422 invalid_topic (never an empty list); for such a subject use tengu_v3_news_ticker_news with search.","query_params":[{"name":"topic","type":"string","required":true,"description":"earnings | dividend | layoffs | lawsuit | mergers (M&A) | pricemovement | tanalysis (technical analysis) | product | ceo | pressrelease | podcast | oil | futures | paywall; anything else is a 422 listing these"},{"name":"ticker","type":"string"},{"name":"items","type":"int","default":50,"min":1,"max":50},{"name":"date_range","type":"string","default":"last7days"}],"admin":false,"public_name":"news_by_topic"},{"name":"tengu_v3_news_sentiment_stats","method":"GET","path":"/api/v3/news/sentiment_stats","group":"v3","description":"Daily news-sentiment rollup for one ticker: a -1.5 to +1.5 score per day with article counts, over a date_range (default last30days). Call it when the user asks how sentiment on X is trending or whether coverage has turned negative; use tengu_v3_news_latest for the actual headlines.","query_params":[{"name":"ticker","type":"string","required":true},{"name":"date_range","type":"string","default":"last30days"}],"admin":false,"display_name":"Sentiment stats","public_name":"news_sentiment_stats"},{"name":"tengu_v3_news_market_sentiment","method":"GET","path":"/api/v3/news/market_sentiment","group":"v3","description":"Daily sentiment of general market and macro news (the articles the source tags with no ticker) over a date_range (default last7days), scored -1.5 to +1.5. It covers untagged news only, so it can differ in sign from tengu_v3_news_all_tickers_sentiment (ticker-tagged news). Call this when the user asks how the macro news backdrop feels right now. partial_days names today and any date before the window, whose scores rest on part of a day.","query_params":[{"name":"date_range","type":"string","default":"last7days"}],"admin":false,"display_name":"Overall market sentiment","public_name":"news_market_sentiment"},{"name":"tengu_v3_news_trending","method":"GET","path":"/api/v3/news/trending","group":"v3","description":"DRILL-DOWN ONLY — never alongside tengu_v3_news_summary (it already includes trending status). The newswire's noise-filtered top stories for a ticker, for when you specifically need the trending ranking on its own. Only stories from the last 72 hours are served (the source's per-ticker list reaches back months); an empty list with a note means nothing recent is trending, and tengu_v3_news_latest has the current headlines.","query_params":[{"name":"ticker","type":"string"}],"admin":false,"display_name":"Trending news","public_name":"news_trending"},{"name":"tengu_v3_news_top_mentions","method":"GET","path":"/api/v3/news/top_mentions","group":"v3","description":"Most-mentioned tickers in the news over a window (default today), optionally filtered by sector, each with mention counts and a sentiment score from -1.5 to +1.5 — a market-attention proxy and the per-stock sentiment ranking. Private companies appear under the source's own codes (P-ANTH), flagged is_listed false. Call this when the user asks which stocks are getting the most buzz or where the crowd's focus is today.","query_params":[{"name":"date_range","type":"string","default":"today"},{"name":"sector","type":"string"}],"admin":false,"display_name":"Trending tickers","public_name":"news_top_mentions"},{"name":"tengu_v3_news_sundown","method":"GET","path":"/api/v3/news/sundown","group":"v3","description":"Curated end-of-day 'sundown' digest — a market-close recap of the day's news from the newswire, one per trading day, newest first. date_range (today, yesterday, lastNdays, MMDDYYYY-MMDDYYYY; New York dates) keeps the digests dated inside it; limit caps how many are served (default 5). A digest is published around 18:45 ET, so 'today' is empty before then and the note names the latest. Call this when the user asks 'what happened in the market today' or wants a daily wrap-up.","query_params":[{"name":"date_range","type":"string"},{"name":"limit","type":"int","default":5,"min":1,"max":50}],"admin":false,"display_name":"Evening digest","public_name":"news_sundown"},{"name":"tengu_v3_news_curated_events","method":"GET","path":"/api/v3/news/curated_events","group":"v3","description":"Structured market events — clusters of articles about one catalyst (earnings, deals, contracts, rating moves), each with a name, summary, tickers and date — filterable by ticker and date_range (default today). The source's events carry no type, so event_type is refused with a 422 (for topic-tagged articles use tengu_v3_news_by_topic). An event's date is when the cluster formed, which can be hours after its first article. Call this when the user asks 'what events happened' or 'any catalysts for X' instead of scanning raw headlines.","query_params":[{"name":"ticker","type":"string"},{"name":"event_type","type":"string","description":"Not supported: any value is refused (422 unsupported_filter); the events carry no type. For topic-tagged articles use tengu_v3_news_by_topic."},{"name":"date_range","type":"string","default":"today"},{"name":"items","type":"int","default":50,"min":1,"max":50}],"admin":false,"public_name":"news_curated_events"},{"name":"tengu_v3_news_ticker_news","method":"GET","path":"/api/v3/news/ticker_news","group":"v3","description":"FILTERED-SEARCH ONLY — reach for this when the user specifies filters (topic, source, sentiment, date_range, article/video, free-text search) or multi-ticker search. Never for plain 'what's the news on X?' (that is tengu_v3_news_summary). Full newswire filter spec; sortby rank or oldestfirst. No sector filter: the source ignores it beside tickers, so it is refused (422 unsupported_filter); tengu_v3_news_category filters by sector.","query_params":[{"name":"tickers","type":"string","required":true,"description":"Comma-separated tickers"},{"name":"items","type":"int","default":50,"min":1,"max":50},{"name":"page","type":"int","default":1,"min":1,"max":50},{"name":"date_range","type":"string"},{"name":"topic","type":"string","description":"one of earnings | dividend | layoffs | lawsuit | mergers (M&A) | pricemovement | tanalysis (technical analysis) | product | ceo | pressrelease | podcast | oil | futures | paywall; unknown is a 422"},{"name":"topic_or","type":"string","description":"comma list from the same topics"},{"name":"topic_exclude","type":"string","description":"comma list from the same topics, e.g. paywall,paylimitwall"},{"name":"source","type":"string"},{"name":"source_exclude","type":"string"},{"name":"news_type","type":"string","enum":["article","video"]},{"name":"sentiment","type":"string","enum":["positive","negative","neutral"]},{"name":"sortby","type":"string","enum":["rank","oldestfirst"]},{"name":"days","type":"int","min":1,"max":30},{"name":"search","type":"string"},{"name":"search_or","type":"string"},{"name":"fallback","type":"bool","default":false}],"admin":false,"display_name":"Ticker news","public_name":"news_ticker_news"},{"name":"tengu_v3_news_ticker_only","method":"GET","path":"/api/v3/news/ticker_only","group":"v3","description":"News stories tagged with ONLY this one ticker — the strictest filter, excluding articles that co-tag competitors or peers. Call this when the user wants pure company-specific coverage without sector noise; use ticker_news for broader filtered search.","query_params":[{"name":"ticker","type":"string","required":true},{"name":"items","type":"int","default":50,"min":1,"max":50},{"name":"page","type":"int","default":1,"min":1,"max":50}],"admin":false,"public_name":"news_ticker_only"},{"name":"tengu_v3_news_multi_ticker","method":"GET","path":"/api/v3/news/multi_ticker","group":"v3","description":"News stories where ALL the listed tickers co-appear in the same article — a correlation feed. Call this when the user asks how two or more companies are linked in the news (deals, rivalries, shared catalysts); use ticker_news for per-ticker coverage.","query_params":[{"name":"tickers","type":"string","required":true},{"name":"items","type":"int","default":50,"min":1,"max":50},{"name":"page","type":"int","default":1,"min":1,"max":50}],"admin":false,"display_name":"Multi-ticker news","public_name":"news_multi_ticker"},{"name":"tengu_v3_news_all_tickers_sentiment","method":"GET","path":"/api/v3/news/all_tickers_sentiment","group":"v3","description":"Market-wide daily sentiment of ticker-tagged news over a date_range (default last7days): one row per date with positive / negative / neutral article counts and a score from -1.5 to +1.5 for the whole tracked universe. It has no per-ticker rows: to rank stocks by news sentiment use tengu_v3_news_top_mentions, which scores each ticker. partial_days names today and any date before the window, whose scores rest on part of a day.","query_params":[{"name":"date_range","type":"string","default":"last7days"},{"name":"page","type":"int","default":1,"min":1,"max":20}],"admin":false,"display_name":"Sentiment per ticker","public_name":"news_all_tickers_sentiment"},{"name":"tengu_v3_news_alerts","method":"GET","path":"/api/v3/news/alerts","group":"v3","description":"Headline-only alert stream — lighter and faster than full news items; category=general for market-wide or tickers for specific names (tickers alone means category=ticker; tickers with category=general is a 422). Call this when the user wants breaking headlines or the very latest on a name and speed matters more than article bodies.","query_params":[{"name":"category","type":"string","enum":["general","ticker"]},{"name":"tickers","type":"string"},{"name":"items","type":"int","default":100,"min":1,"max":100},{"name":"page","type":"int","default":1,"min":1,"max":50}],"admin":false,"public_name":"news_alerts"},{"name":"tengu_v3_news_ratings","method":"GET","path":"/api/v3/news/ratings","group":"v3","description":"Analyst rating actions — upgrades, downgrades, and initiations, filterable by tickers, rating_type, and date_range; history goes back to 2022-04-08. PRIMARY tool for 'any recent upgrades or downgrades on X?' and for gauging how sell-side conviction is shifting. The feed carries only part of the street's actions (feed_coverage 'partial'; most price-target changes on a maintained rating are missing): an empty list means none in the feed, not that no analyst acted.","query_params":[{"name":"tickers","type":"string"},{"name":"rating_type","type":"string","enum":["upgrade","downgrade","initiation"]},{"name":"date_range","type":"string"},{"name":"items","type":"int","default":50,"min":1,"max":50},{"name":"page","type":"int","default":1,"min":1,"max":50}],"admin":false,"display_name":"Analyst ratings","public_name":"news_ratings"},{"name":"tengu_v3_news_event_by_id","method":"GET","path":"/api/v3/news/event_by_id","group":"v3","description":"All news items belonging to one clustered event, looked up by eventid, paginated. Call this when you already have an eventid from another news result and the user wants the full article set behind that single catalyst or story cluster.","query_params":[{"name":"eventid","type":"string","required":true},{"name":"items","type":"int","default":50,"min":1,"max":50},{"name":"page","type":"int","default":1,"min":1,"max":20}],"admin":false,"display_name":"News event","public_name":"news_event_by_id"},{"name":"tengu_v3_news_category","method":"GET","path":"/api/v3/news/category","group":"v3","description":"Category-scoped news feed: section=general for market-wide or alltickers for company-tagged stories, filterable by topic, sector, industry, and source. Call this when the user wants themed or sector-level news rather than coverage of a specific ticker.","query_params":[{"name":"section","type":"string","default":"general","enum":["general","alltickers"]},{"name":"topic","type":"string","description":"one of earnings | dividend | layoffs | lawsuit | mergers (M&A) | pricemovement | tanalysis (technical analysis) | product | ceo | pressrelease | podcast | oil | futures | paywall; unknown is a 422"},{"name":"sector","type":"string"},{"name":"industry","type":"string"},{"name":"source","type":"string"},{"name":"items","type":"int","default":50,"min":1,"max":50},{"name":"page","type":"int","default":1,"min":1,"max":50},{"name":"date_range","type":"string"}],"admin":false,"public_name":"news_category"},{"name":"tengu_v3_news_summary","method":"GET","path":"/api/v3/news/summary/{ticker}","group":"v3","description":"One-shot news intelligence for a ticker: stories of the last 24 hours (news_count_24h counts them all; the newest 20 are listed), 7-day sentiment stats, trending stories of the last 72 hours, structured events, and analyst actions in a single parallel fetch (90s TTL). THE primary tool for 'what's the news on X?' — this ALONE answers most single-ticker news questions; do NOT stack other news tools in the same round unless it returns nothing useful. analyst_actions carries only part of the street's rating actions (analyst_actions_note): an empty list is none in the feed, not none taken.","path_params":["ticker"],"admin":false,"display_name":"News brief","public_name":"news_summary"},{"name":"tengu_v3_fundamentals_income_statements","method":"GET","path":"/api/v3/fundamentals/income_statements","group":"v3","description":"SEC-reported income statements (revenue to net income, EPS), quarterly, annual or TTM (default quarterly, last 8). Rows that do not add up, and every bank, insurer or IFRS filer's, are checked against its SEC filing. statement_check.status is sec_confirmed, sec_corrected (a line taken from the filing: field_basis names it, the prior figure is vendor_<field>) or sec_check_unavailable (withheld; retry shortly). A withheld line is null, its reason in fields_withheld and its note in field_notes; fields_unverified: {field: reason} for kept figures the filing cannot confirm; field_basis served:false holds check_values only. per_share_restated marks a restated EPS. Banks show net_interest_income, not gross profit. EPS is as filed; *_split_adjusted puts it on today's share basis. quarters_missing lists absent quarters, newest first, with any SEC reports past the newest row (newer_filing_available). eps_repair logs an EPS fixed against its net income. An unknown symbol is refused 404 unknown_ticker (not billed).","query_params":[{"name":"ticker","type":"string","required":true},{"name":"period","type":"string","default":"quarterly","enum":["annual","quarterly","ttm"]},{"name":"limit","type":"int","default":8,"min":1,"max":200}],"admin":false,"display_name":"Income statement","public_name":"fundamentals_income_statements"},{"name":"tengu_v3_fundamentals_balance_sheets","method":"GET","path":"/api/v3/fundamentals/balance_sheets","group":"v3","description":"SEC-reported balance sheets for a ticker: assets, liabilities and equity per period, quarterly or annual (default quarterly, last 8). A fiscal year-end sheet appears as Q4 (period_source annual_report). Rows whose accounting does not add up, and every bank, insurer or IFRS filer's rows, are checked against the company's SEC filing, with statement_check, field_basis, vendor_<field>, fields_withheld and field_notes as in fundamentals_income_statements. short_term_debt is current debt (borrowings, commercial paper, current maturities) when the filing was read (short_term_debt_basis says which). A total liabilities the filer does not tag is total assets less total equity (field_basis). long_term_debt_status not_found_in_sec_companyfacts: no SEC fact, not no line. newer_filing_available: SEC has a later report. Banks show net_loans and deposits, with no current assets or receivables. An unknown symbol is refused 404 unknown_ticker (not billed).","query_params":[{"name":"ticker","type":"string","required":true},{"name":"period","type":"string","default":"quarterly","enum":["annual","quarterly","ttm"]},{"name":"limit","type":"int","default":8,"min":1,"max":200}],"admin":false,"display_name":"Balance sheet","public_name":"fundamentals_balance_sheets"},{"name":"tengu_v3_fundamentals_cash_flow_statements","method":"GET","path":"/api/v3/fundamentals/cash_flow_statements","group":"v3","description":"SEC EDGAR cash-flow statements for a ticker — operating, investing, and financing flows per period, quarterly or annual (default quarterly, last 8 periods). Call this when the user asks about cash generation, capex, buybacks, or how earnings convert to actual cash. investment_sales is proceeds from sales only, excluding maturities (investment_sales_basis). change_in_working_capital is null with change_in_working_capital_status, as in fundamentals_full: the source's figure is not total working capital. Where the balance sheets confirm it is the receivables change it is served as change_in_receivables (cash-flow sign: negative when receivables rose), and operating_cash_flow_components sum to operating_cash_flow. A real ticker with no rows stays a 200; a symbol the platform does not know at all, current or delisted, is refused 404 unknown_ticker (not billed).","query_params":[{"name":"ticker","type":"string","required":true},{"name":"period","type":"string","default":"quarterly","enum":["annual","quarterly","ttm"]},{"name":"limit","type":"int","default":8,"min":1,"max":200}],"admin":false,"display_name":"Cash flow","public_name":"fundamentals_cash_flow_statements"},{"name":"tengu_v3_fundamentals_all","method":"GET","path":"/api/v3/fundamentals/all","group":"v3","description":"All three financial statements (income, balance sheet, cash flow) for a ticker in one call (default quarterly, last 4). Income and balance rows carry the same statement_check as fundamentals_income_statements and fundamentals_balance_sheets. An unknown symbol is refused 404 unknown_ticker (not billed).","query_params":[{"name":"ticker","type":"string","required":true},{"name":"period","type":"string","default":"quarterly","enum":["annual","quarterly","ttm"]},{"name":"limit","type":"int","default":4,"min":1,"max":200}],"admin":false,"public_name":"fundamentals_all"},{"name":"tengu_v3_fundamentals_metrics","method":"GET","path":"/api/v3/fundamentals/metrics","group":"v3","description":"Derived financial-metric rows per period for a ticker — P/E, ROE, margins, FCF yield, debt ratios — quarterly, annual, or TTM (default quarterly, last 4 periods). Call this when the user asks about valuation or quality ratios and their trend without needing raw statement line-items. period=ttm serves ONE row for the latest four consecutive fiscal quarters: margins, ROE, ROA and asset turnover on TTM flows over the window's quarter-end balance sheet, TTM EPS on today's share basis, balance ratios at that quarter end; ratios are FRACTIONS, with definitions, ttm_status and null_reasons (a field that cannot be computed on four consecutive quarters is null); a financial issuer's debt ratios exclude deposits (debt_ratios_basis; issuer_class_basis says how the class was decided). A real ticker with no rows stays a 200; a symbol the platform does not know at all, current or delisted, is refused 404 unknown_ticker (not billed).","query_params":[{"name":"ticker","type":"string","required":true},{"name":"period","type":"string","default":"quarterly","enum":["annual","quarterly","ttm"]},{"name":"limit","type":"int","default":4,"min":1,"max":200}],"admin":false,"display_name":"Key metrics (full)","public_name":"fundamentals_metrics"},{"name":"tengu_v3_fundamentals_metrics_snapshot","method":"GET","path":"/api/v3/fundamentals/metrics_snapshot","group":"v3","description":"Latest fundamentals snapshot for a ticker in one call: profile, latest fiscal year and quarter, a trailing-twelve-months block (income, cash flow, ratios), the latest quarter-end balance sheet, the latest quarter's ratios and fiscal-year growth. The blocks cover DIFFERENT periods and units, and each says so: `period` (type quarter, fiscal_year, ttm (four consecutive quarters), partial_ttm (anything less) or point_in_time, with fiscal_year, fiscal_quarter, start, end) and `units` per numeric field (percent, fraction, usd, usd_per_share, multiple, shares, count; reporting_currency with a `currency` code when not US dollars). `ttm.ttm_ratios` and `growth` are PERCENT numbers (roe_ttm 84.23 = 84.23%); `ratios` is FRACTIONS of the latest quarter alone, not annualized (roe 0.2812 = 28.12% that quarter); ratio blocks carry `definitions`. TTM sums four CONSECUTIVE fiscal quarters: with fewer, or a gap, the sums are null and ttm_status says why; a field some quarters leave empty is summed over the rest and named in ttm_underfilled_fields. TTM EPS is on today's share basis (eps_ttm_basis). Dividends: `dividend` holds split-adjusted trailing and indicated dividends per share with their dates; in `dividends`, dividends_per_share is the fiscal year's paid over that year's shares as filed, payout_ratio is a PERCENT, and dividend_history rows carry per_share_split_adjusted. Call this for a quick 'how profitable is X, how fast is it growing' check; use fundamentals_metrics when the user needs the per-period history. Statement blocks carry statement_check; balance_sheet_summary is checked too. total_debt and net_debt are null with debt_components_missing when a part is missing, never one part alone; debt ratios follow the checked sheet (debt_basis). A financial issuer's (a bank, insurance carrier, broker-dealer or repo-funded REIT, by its SEC industry code and balance sheet) net_debt is null (net_debt_status) and its debt excludes deposits (total_debt_basis, debt_ratios_basis; issuer_class_basis says how the class was decided). Blocks of a quarter SEC has a later report for carry newer_filing_available. An unknown symbol is refused 404 unknown_ticker (not billed).","query_params":[{"name":"ticker","type":"string","required":true}],"admin":false,"display_name":"Key metrics (snapshot)","public_name":"fundamentals_metrics_snapshot"},{"name":"tengu_v3_fundamentals_insider_trades","method":"GET","path":"/api/v3/fundamentals/insider_trades","group":"v3","description":"Form-4 insider transactions for one ticker — officer and director buys and sells (default limit 50). Call this when the user asks whether insiders are buying or selling a stock, or wants insider-conviction evidence for a name. Rows carry is_derivative (an option or RSU line, whose shares_after_transaction is a derivative holding), security_title when the source names it, and transaction_code M reads 'Exercise or conversion of derivative (incl. RSU vesting)'. price_basis says what a price is per: for an ADR (listing_class adr) Form 4 prices are per ORDINARY share, and rows carry price_per_adr when adr_ratio is known (TSM 5). listing_class is the requested listing's class (listing_class_applies_to), and security_title_status / insider_role_status say when the source names no security or role. price is null with price_status zero_or_not_reported where the source's 0 can stand for a footnote-only price (the $0 of a gift or a transfer by will is kept). Rows come in each filing's own order and a filing is never split: whole filings while they fit in limit, and a newest filing longer than limit served whole (limit_exceeded; truncated, rows_available). A real ticker with no rows stays a 200; a symbol the platform does not know at all, current or delisted, is refused 404 unknown_ticker (not billed).","query_params":[{"name":"ticker","type":"string","required":true},{"name":"limit","type":"int","default":50,"min":1,"max":500}],"admin":false,"display_name":"Insider Form-4 filings","public_name":"fundamentals_insider_trades"},{"name":"tengu_v3_fundamentals_institutional_ownership","method":"GET","path":"/api/v3/fundamentals/institutional_ownership","group":"v3","description":"13F institutional holdings for one ticker, itemized by holding institution (default limit 50). Call this when the user asks which institutions or funds own a stock or how concentrated institutional ownership is. The 13F archive ends a quarter behind EDGAR: newest_report_period, vendor_ceiling and is_stale say so. When the archive cannot be read it returns 503 upstream_unavailable (error_code archive_read_failed; not billed), never an empty list.","query_params":[{"name":"ticker","type":"string","required":true},{"name":"limit","type":"int","default":50,"min":1,"max":500}],"admin":false,"display_name":"Institutional ownership","public_name":"fundamentals_institutional_ownership"},{"name":"tengu_v3_fundamentals_companyfacts","method":"GET","path":"/api/v3/fundamentals/companyfacts/{ticker}","group":"v3","description":"Directory of every as-reported XBRL concept (us-gaap/dei/ifrs-full) a company has filed — unit(s), observation count and period coverage — from SEC EDGAR's live companyfacts document. Call it FIRST to find the concept tag for /fundamentals/xbrl/{ticker}/{concept}. Point-in-time, no vendor restatement. source is sec_edgar_companyfacts_live, or archive when SEC could not be read (then is_stale and the archive's age are stated); as_of is when the document was read and last_filed the newest filing date among its facts.","path_params":["ticker"],"query_params":[{"name":"search","type":"string","description":"Case-insensitive substring filter on the XBRL concept tag"},{"name":"limit","type":"int","default":400,"min":1,"max":2000}],"admin":false,"public_name":"xbrl_concepts"},{"name":"tengu_v3_fundamentals_xbrl","method":"GET","path":"/api/v3/fundamentals/xbrl/{ticker}/{concept}","group":"v3","description":"One XBRL concept's as-reported history — period, value, SEC form, accession, filed date — from SEC EDGAR's live companyfacts document. Call it for exact as-filed fundamentals: as_of= for point-in-time (no restatement look-ahead; echoed as as_of), history=true for all restatements; find tags via /fundamentals/companyfacts. fy/fp are the fiscal year/period of the FILING that carried the fact (a 10-Q repeats the prior year-end balance under its own Q1); period_fy/period_fp/period_months are the fact's own period. source (sec_edgar_companyfacts_live or archive), data_as_of, last_filed and is_stale date the answer.","path_params":["ticker","concept"],"query_params":[{"name":"taxonomy","type":"string","description":"Pin the taxonomy (us-gaap/dei/ifrs-full); default auto-search"},{"name":"unit","type":"string","description":"Filter to one unit (USD, shares, USD/shares)"},{"name":"form","type":"string","description":"Filter to one SEC form (10-K, 10-Q)"},{"name":"start","type":"string","description":"Earliest reporting-period end date YYYY-MM-DD"},{"name":"end","type":"string","description":"Latest reporting-period end date YYYY-MM-DD"},{"name":"as_of","type":"string","description":"Point-in-time: only values filed on or before this date (no restatement look-ahead)"},{"name":"history","type":"bool","default":false,"description":"True = full disclosure history (all restatements); False = one best value per period"},{"name":"limit","type":"int","default":500,"min":1,"max":5000}],"admin":false,"public_name":"xbrl_concept_history"},{"name":"tengu_v3_tape_options_chain","method":"GET","path":"/api/v3/tape/options_chain/{ticker}","group":"v3","description":"Historical OPTIONS CHAIN slice for one underlying on one snapshot day from the API's own daily chain capture — per contract: strike, expiry, dte, bid/ask/mid/last, day volume + VWAP, implied volatility, the full greeks (delta/gamma/theta/vega), open interest and underlying price, plus a summary over the captured contracts (contract/expiration counts, put/call OI + volume ratios, front-month ATM IV). The capture keeps a bounded near-the-money slice of each chain (since 2026-09-23: expiries within 120 days and strikes within 30% of spot, capped per underlying, 150 by default), not the full listed chain, so the summary's totals and put/call ratios describe that slice and can differ widely from the whole chain's; coverage states the slice and its rule. For full-chain put/call volume and open interest use tengu_v3_intel_options_volume. Use it to reconstruct the IV surface, greeks or OI distribution AS IT STOOD on a past day, find where OI/volume concentrated, or pull the near-the-money strikes around an event. Omit date for the latest captured day (reported as snapshot_day); filter by side, expiration/dte, min OI/volume or a moneyness band; sort by open interest or dollar notional. Capture begins 2026-05-10. For the raw options TRADE tape use tengu_v3_tape_options; for live GEX/dealer flow use the options_flow tools.","path_params":["ticker"],"query_params":[{"name":"date","type":"string","description":"snapshot day YYYY-MM-DD — omit for the latest captured day"},{"name":"contract_type","type":"string","enum":["call","put"],"description":"filter one side (also accepts C/P); default both"},{"name":"expiration","type":"string","description":"filter to one expiration date YYYY-MM-DD"},{"name":"min_dte","type":"int","min":0,"max":3650,"description":"minimum days-to-expiry"},{"name":"max_dte","type":"int","min":0,"max":3650,"description":"maximum days-to-expiry"},{"name":"min_open_interest","type":"float","min":0,"description":"only contracts with open_interest >= this"},{"name":"min_volume","type":"float","min":0,"description":"only contracts with day_volume >= this"},{"name":"moneyness","type":"float","min":0,"max":5.0,"description":"keep strikes within +/- this fraction of the underlying (0.1 = the near-the-money +/-10% band)"},{"name":"sort","type":"string","default":"open_interest","enum":["open_interest","notional"]},{"name":"limit","type":"int","default":100,"min":1,"max":2000}],"admin":false,"capability_tags":["heavy"],"public_name":"tape_options_chain"},{"name":"tengu_v3_intel_vol_surface","method":"GET","path":"/api/v3/intel/vol_surface/{ticker}","group":"v3","description":"HISTORICAL standardized implied-vol SURFACE for a company from a licensed academic archive, joined from a plain equity ticker. Returns the standardized surface grid: for each maturity (days = 30/60/91/182/365) and delta node, per call/put the interpolated implied volatility and its dispersion — the vol skew + term structure behind risk-reversals, butterflies and the ATM vol term structure, as it stood on a past session. The archive is LAGGED by a year or more, so omitting date serves its latest-available surface, never today's vol; the archive's end date is served in the response (available_dates.end). as_of and age_days say how old the served surface is; is_stale says whether the archive is behind the yearly schedule its source publishes on (freshness.next_due names the next due date), not whether it is recent. Pass date=YYYY-MM-DD for a specific session and days= to pin one maturity. For CURRENT vol use /intel/iv_analytics (IV rank, skew, term structure) or /intel/options_chain (live per-contract IV).","path_params":["ticker"],"query_params":[{"name":"date","type":"string","description":"Surface date YYYY-MM-DD; OMIT for the latest-available surface (the archive is lagged, so a today-relative date reads empty). Served date + available range are reported in the response."},{"name":"days","type":"float","description":"Filter to ONE maturity in calendar days (30/60/91/182/365); omit for the full term structure"},{"name":"limit","type":"int","default":500,"min":1,"max":2000}],"admin":false,"public_name":"intel_vol_surface"},{"name":"tengu_v3_funds_mutual_fund_ownership","method":"GET","path":"/api/v3/funds/mutual_fund_ownership/{ticker}","group":"v3","description":"Which mutual funds hold a stock — each fund's portfolio number (fund names are not held yet: fund_name is null, and security_name is the stock held), percent_tna, shares and market value, largest first, plus report_dt and n_funds, from the survivor-bias-free holdings archive (quarterly from 2002; no date = the latest quarter-end held, served as coverage.end). Call it for mutual-fund demand base or holder concentration; for 13F institutional holders use /intel/sec13f.","path_params":["ticker"],"query_params":[{"name":"date","type":"string","description":"Report date YYYY-MM-DD (a quarter-end); omit for the LATEST available report — the archive is quarterly and lags"},{"name":"top","type":"int","default":100,"min":1,"max":5000,"description":"Max funds returned, largest position (market_val) first"},{"name":"min_market_val","type":"number","min":0,"description":"Only funds whose position market value (USD) is at least this (e.g. 1e9 for billion-dollar holders)"}],"admin":false,"capability_tags":["heavy"],"public_name":"funds_mutual_fund_ownership"},{"name":"tengu_v3_factor_predictors","method":"GET","path":"/api/v3/factors/predictors/{ticker}","group":"v3","description":"academic-style predictor panel for one stock — a compact vector of 13 accounting characteristics built from QUARTERLY statements (accruals, asset growth, PP&E growth, gross profit / assets, operating profit / assets, cash-to-assets, leverage change, earnings consistency, revenue growth, positive net-income and operating-income flags, (total assets - PP&E) / current liabilities, net share issuance), one row per fiscal quarter dated at the report month-end. Flow ratios are ONE quarter's flows, not annualised; current_ratio is withheld (the archive's column is not a current ratio) and predictor_glossary / units / withheld_predictors say what each value is. Call it for a ready-made feature vector when you don't need the full ~460-column factor panel. Returns the series newest-last, or with latest=true only the single most-recent row as a name->value map; with no start/end it serves the LATEST AVAILABLE rows (lagged quarterly archive) and reports the actual window. Ticker is resolved to its internal security key automatically (the table has no ticker column).","path_params":["ticker"],"query_params":[{"name":"start","type":"string","description":"ISO date series start (omit both dates for the latest available rows)"},{"name":"end","type":"string","description":"ISO date series end (omit both for the latest available rows)"},{"name":"latest","type":"bool","default":false,"description":"True = only the single most-recent predictor row (name->value map)"},{"name":"limit","type":"int","default":600,"min":1,"max":2000,"description":"max rows in series mode (newest kept); ignored when latest=true"}],"admin":false,"public_name":"factor_predictors"},{"name":"tengu_v3_fundamentals_segments","method":"GET","path":"/api/v3/fundamentals/segments/{ticker}","group":"v3","description":"Business + geographic SEGMENT breakdown for one company — decomposes a fiscal period into reportable segments by line of business, geography, ASC-280 operating segment and US state, each with sales, revenue, operating income and SIC, grouped by segment type. Call it to see WHERE a company earns: revenue mix by region (e.g. Greater China share) or which line of business carries the margin. Internally keyed (the ticker is resolved via the point-in-time name master, most-recent row); the archive lags, so with no year/date it returns the LATEST available period and reports the datadate served. Values are in the reported currency, fundamentals's millions convention.","path_params":["ticker"],"query_params":[{"name":"year","type":"int","min":1960,"max":2100,"description":"Fiscal year to return (matched on the segment datadate's year); omit for the latest available period"},{"name":"date","type":"string","description":"Exact segment datadate YYYY-MM-DD (overrides year); use available_datadates to pick a valid one"},{"name":"stype","type":"string","description":"Return only one segment type: business / geographic / operating / state (or the raw code BUSSEG/GEOSEG/OPSEG/STSEG); default all"},{"name":"limit","type":"int","default":200,"min":1,"max":2000,"description":"Max segment rows across all groups"}],"admin":false,"public_name":"fundamentals_segments"},{"name":"tengu_v3_fundamentals_sec_filings","method":"GET","path":"/api/v3/fundamentals/sec_filings","group":"v3","description":"SEC filings list for a ticker — 10-K, 10-Q, 8-K, S-1 and more, with an optional form_type filter (default limit 20). Call this when the user asks what a company has filed or wants to locate a specific filing type. Read from SEC EDGAR, the source of record (source 'sec-edgar'), whose answer stands even when empty; is_partial=true means a heavy filer's history was only searched back to searched_back_to, so older filings may exist. When EDGAR cannot answer or lists none, a fallback index serves it (source 'vendor:filings-index', with fallback_reason and a staleness_note) and may lag EDGAR by weeks; its is_stale is null under a form_type filter, where the lag cannot be measured. Every answer carries newest_item_date. accepted_date is US/Eastern wall-clock time (accepted_date_timezone). A real ticker with no rows stays a 200; a symbol the platform does not know at all, current or delisted, is refused 404 unknown_ticker (not billed).","query_params":[{"name":"ticker","type":"string","required":true},{"name":"limit","type":"int","default":20,"min":1,"max":200},{"name":"form_type","type":"string"}],"admin":false,"display_name":"SEC filings","public_name":"fundamentals_sec_filings"},{"name":"tengu_v3_fundamentals_company_facts","method":"GET","path":"/api/v3/fundamentals/company_facts","group":"v3","description":"Static company profile for one ticker — sector, industry, CIK, exchange, market cap and employee count (employees; the source gives no as-of date). sector is an SIC DIVISION ('Manufacturing' for AAPL), not a GICS sector: sic_division repeats it and sector_taxonomy names it. Market cap is on the prior close. Call it to know what a company is and how big it is before deeper analysis. Not the XBRL corpus — that discovery lives at /fundamentals/companyfacts/{ticker}. A malformed ticker returns 422 invalid_ticker before any vendor call (not billed). A real ticker with no rows stays a 200; a symbol the platform does not know at all, current or delisted, is refused 404 unknown_ticker (not billed).","query_params":[{"name":"ticker","type":"string","required":true}],"admin":false,"display_name":"Company facts","public_name":"fundamentals_company_facts"},{"name":"tengu_v3_fundamentals_prices","method":"GET","path":"/api/v3/fundamentals/prices","group":"v3","description":"Historical OHLCV bars for one ticker at second/minute/hour/day/week/month granularity (interval_multiplier for e.g. 5-minute bars; start_date/end_date window, default limit 1000). Call this when the user asks for price history, returns over a window, or intraday bars; for the latest quote use /fundamentals/price_snapshot. CRYPTO: pass asset_class=crypto for BTC/ETH/SOL/LTC/LINK etc. Several crypto symbols are ALSO US-listed equity tickers (BTC is a Grayscale trust at ~$29; LINK is Interlink Electronics), so a bare ticker returns the EQUITY. Never use an equity price for a crypto asset. With no end_date the window runs through TODAY's session (real time; it used to end yesterday), and the newest bar may still be forming: partial:true, never a final close. data_through (= as_of) is how far the data runs: the last bar's end, capped at the fetch. session_complete is false while bars can still arrive in the window (the tape prints until 20:00 ET, or a later trading day is in it). No bars yet is a 200 with items [] (an answer, not an outage); end_date before start_date is a 422 invalid_date_range, and an impossible date (2026-09-31) a 422 invalid_date. Forex (C:) and crypto (X:) tickers on this path keep a UTC day: a day bar runs 00:00-24:00 UTC and is partial:true until it ends, and session_complete follows that UTC day. Equity bars from the primary source are SPLIT-ADJUSTED to the share basis in force when fetched (adjusted:true, adjustment_basis splits), not dividend-adjusted: a bar before a split is not the traded price. Bars the fallback source served say adjusted:null, adjustment_basis unverified. For as-traded daily prices with adjustment factors use /prices/history. Equity volume is whole shares from the daily aggregate (fractional-share trades rounded to the nearest share); forex and crypto volume is as the source counts it.","query_params":[{"name":"ticker","type":"string","required":true},{"name":"asset_class","type":"string","default":"equity","enum":["equity","crypto"],"description":"'crypto' returns the real crypto asset; omit or 'equity' returns the US-listed equity of the same ticker"},{"name":"interval","type":"string","default":"day","enum":["second","minute","hour","day","week","month"]},{"name":"interval_multiplier","type":"int","default":1,"min":1,"max":60},{"name":"start_date","type":"string","description":"YYYY-MM-DD"},{"name":"end_date","type":"string","description":"YYYY-MM-DD"},{"name":"limit","type":"int","default":1000,"min":1,"max":5000,"description":"the most recent N bars in the window"}],"admin":false,"display_name":"Price history","public_name":"fundamentals_prices"},{"name":"tengu_v3_fundamentals_price_snapshot","method":"GET","path":"/api/v3/fundamentals/price_snapshot","group":"v3","description":"Latest quote for one ticker. Call this when the user asks what the price is now or how the stock is moving today; for history use /fundamentals/prices. price is the last trade in ANY session; price_session says which (the closing auction print, stamped just after the bell, is regular) and as_of when. Sessions, US Eastern: pre 04:00-09:30, regular 09:30-16:00, post 16:00-20:00 (half-days: regular to 13:00, post to 17:00), closed otherwise and on weekends and exchange holidays. market_session (and session, the same value) is the session when the answer is served. day_change = price - prev_close, and day_change_percent is that over prev_close in percent points (1.5 = 1.5%); prev_close is the regular-session close of prev_close_date. Outside regular hours they include extended-hours trading. Every change is the exact price difference and every percent has 6 significant figures. For how the stock did in its latest regular session use regular_session {date, status in_progress|closed, open, high, low, close (null until final, 5 minutes after the bell), last, volume (whole shares, extended hours included: once the session is final, the daily aggregate's, the figure /fundamentals/prices serves; while it forms, the live day bar's running tally, which can differ by a few hundred shares), prev_close, prev_close_date, change, change_percent}; for the move since that close use extended_hours {session pre|post, price, as_of, reference_close, reference_close_date, change, change_percent}, null in regular hours or when the last trade was a regular-session trade. day_* is the bar of day_bar_date (before the open, the previous session's); day_volume is its running tally in whole shares. bid/ask are served only while the exchange is in a session, and only a quote set during that session (quote_as_of, when the quote last changed, at or after the session's start); else null. session_detail_status says why a session field is null: partial (a date or an earlier close could not be established) or unavailable. State the session and date with any move; never report an extended-hours move as a session's change. CRYPTO: pass asset_class=crypto for BTC/ETH/SOL/LTC/LINK etc. Several crypto symbols are ALSO US-listed equity tickers (BTC is a Grayscale trust at ~$29; LINK is Interlink Electronics), so a bare ticker returns the EQUITY. Never use an equity price for a crypto asset. Check is_stale before using the price. VALUATION (equity, on the live price, when valuation_status is 'ok'; otherwise null): pe_ttm = price / eps_ttm (diluted, four consecutive fiscal quarters, today's share basis); forward_pe = pe_ttm / (1 + the latest fiscal year's EPS growth, or net-income growth when a split sits between the years), trailing arithmetic, NOT an analyst consensus, and null when that growth is zero or negative (forward_pe_status says why); market_cap = price x market_cap_shares, the SEC cover page's shares outstanding when current, else the reference count, else the latest balance sheet's, else the latest quarter's weighted-average basic count (market_cap_shares_basis, market_cap_shares_as_of), null for a listing that is not the issuer's equity (a note, preferred, warrant or ETN), a listing without a share count of its own, and when the split history cannot be read now (market_cap_shares_status says why or when it is provisional); dividend_yield is a FRACTION (0.0225 = 2.25%): split-adjusted regular cash dividends with an ex-date in the last 365 days over the price, null for a non-payer; dividend_yield_indicated uses the latest declared regular dividend x payments per year; `dividend` gives the per-share figures, dates and status; units names each unit.","query_params":[{"name":"ticker","type":"string","required":true},{"name":"asset_class","type":"string","default":"equity","enum":["equity","crypto"],"description":"'crypto' returns the real crypto asset; omit or 'equity' returns the US-listed equity of the same ticker"}],"admin":false,"display_name":"Price snapshot (fundamentals)","public_name":"fundamentals_price_snapshot"},{"name":"tengu_v3_fundamentals_news","method":"GET","path":"/api/v3/fundamentals/news","group":"v3","description":"Curated news articles for one ticker from the fundamentals market-data feed, with start_date/end_date filtering (default 50). Call it for ticker-scoped headlines while working inside fundamentals; it is distinct from the primary news surface — use the news tools for broad or breaking coverage.","query_params":[{"name":"ticker","type":"string","required":true},{"name":"limit","type":"int","default":50,"min":1,"max":100},{"name":"start_date","type":"string","description":"YYYY-MM-DD"},{"name":"end_date","type":"string","description":"YYYY-MM-DD"}],"admin":false,"display_name":"Company news","public_name":"fundamentals_news"},{"name":"tengu_v3_fundamentals_full","method":"GET","path":"/api/v3/fundamentals/full/{ticker}","group":"v3","description":"One-shot fundamentals bundle for a ticker, fetched in parallel: the metrics snapshot (same blocks and labels as fundamentals_metrics_snapshot), statements in MATCHED periods (income_statement_ttm with cash_flow_ttm, income_statement_latest_quarter with cash_flow_latest, balance_sheet_latest at the quarter end; `period_pairs` says which match) and company facts. Every block carries `period` and `units`. Cash-flow panes reconcile: the fields in `operating_cash_flow_components` sum to operating_cash_flow; change_in_working_capital is null with a status because the source's figure is not working capital. Insider trades (the last 5 rows, or the newest Form 4 whole when it has more lines, with insider_trades_note) and the top 10 institutional holders (13F, with report period and freshness) need a plan with the funds product; without it they are null with status plan_required. A null pane always has a status; [] means none reported. PRIMARY tool for 'give me the full fundamental picture of X' — call it instead of assembling the pieces one by one. Snapshot statement blocks carry statement_check.","path_params":["ticker"],"admin":false,"display_name":"Fundamentals","public_name":"fundamentals_full"},{"name":"tengu_v3_fundamentals_company_full","method":"GET","path":"/api/v3/fundamentals/company_full/{ticker}","group":"v3","description":"One-call company snapshot: profile, latest fiscal year and quarter, trailing twelve months (income, cash flow with its operating bridge, ratios), the latest quarter-end balance sheet, the latest quarter's ratios and fiscal-year growth. Every block carries `period` and `units`: `ratios` are FRACTIONS of one quarter, `ttm.ttm_ratios` and `growth` are PERCENT numbers. latest_annual, latest_quarterly, income_statement_ttm and balance_sheet_mrq carry statement_check (as in fundamentals_income_statements); newer_annual_report flags a latest year a newer annual report superseded. balance_sheet_summary is checked too; debt totals, debt_basis and newer_filing_available as in fundamentals_metrics_snapshot.","path_params":["ticker"],"admin":false,"display_name":"Company profile","public_name":"fundamentals_company_full"},{"name":"tengu_v3_fundamentals_growth","method":"GET","path":"/api/v3/fundamentals/growth","group":"v3","description":"Growth metrics — YoY, 3Y CAGR, 5Y CAGR and margin trends; accepts comma-separated tickers for one-call bulk comparison. Call this when the user asks how fast a company is growing, whether margins are trending up, or to compare growth across several names. Every figure is a PERCENT number (CAGRs per year) for the row's fiscal_year, not TTM; see units. Revenue growth beyond +-100% is checked against the issuer's SEC annual report on one revenue concept in both years: growth_status sec_confirmed (served as sent), vendor_concept_mismatch (the SEC figures are served, the 3y/5y CAGRs recomputed on the same concept or null, the margins, computed on the contradicted revenue, withheld into vendor_margins; the source's figures stay in vendor_* fields), sec_check_pending or unverified_outlier (null, with revenue_growth_basis.reason). revenue_growth_basis names the concept, both periods, values and the filing. When the answer is empty and every symbol asked for is unknown to the platform (current or delisted), it returns 404 unknown_ticker (not billed). Otherwise symbols_unknown lists requested symbols with no row that the platform does not know.","query_params":[{"name":"tickers","type":"string","required":true,"description":"Comma-separated tickers, e.g. AAPL,MSFT."},{"name":"limit","type":"int","default":1,"min":1,"max":20,"description":"1-20. The source answers one row per ticker, its latest fiscal year, whatever the limit (checked 2026-09-29 with limit 2 and 3)."}],"admin":false,"display_name":"Growth trajectory","public_name":"fundamentals_growth"},{"name":"tengu_v3_fundamentals_dividends","method":"GET","path":"/api/v3/fundamentals/dividends","group":"v3","description":"Dividend profile per ticker — DPS, payout ratio, consecutive-growth streak and 10Y history; accepts comma-separated tickers. Call this for any dividend-safety, income or 'how long has X raised its dividend' question. dividend_history[].per_share is as filed; per_share_split_adjusted restates it on today's share basis (use it for any trend: a split otherwise reads as a cut). dividend_per_share_growth_yoy_pct and years_consecutive_per_share_growth are per share; the *_growth fields without it are TOTAL dollars paid. payout_ratio is a PERCENT; dividends_paid_fiscal_year is the fiscal year's total. `dividend` gives trailing and indicated dividends per share with their dates and status. When the answer is empty and every symbol asked for is unknown to the platform (current or delisted), it returns 404 unknown_ticker (not billed). Otherwise symbols_unknown lists requested symbols with no row that the platform does not know.","query_params":[{"name":"tickers","type":"string","required":true,"description":"Comma-separated tickers"}],"admin":false,"display_name":"Dividends","public_name":"fundamentals_dividends"},{"name":"tengu_v3_fundamentals_peers","method":"GET","path":"/api/v3/fundamentals/peers/{ticker}","group":"v3","description":"Same-industry comparables for a ticker (default 10): the company's GICS sub-industry among US exchange listings (its industry, then industry group, only when too few), with trailing-twelve-month revenue, growth, net margin and ROE in US dollars. Size is TTM revenue; banks and brokers are sized by total assets and their revenue fields are null. Peers under min_relative_size of the company's size are dropped; left at its default (0.10), the floor steps down to 0.05, 0.02 and 0.01 until `limit` clear it, and peer_filter_stats.min_relative_size_applied says how far. Each peer's peer_basis names the GICS level it shares; `peer_selection_basis` is own_data_gics, or vendor_industry when our data cannot size the company (peer_universe_status says why; it is loading for 10-35 s after a restart). `peers_status` says ok, none_after_size_filter, none_after_data_error_filter, none_in_industry, vendor_no_peers or vendor_unavailable. Call this for a company's competitors or how it stacks up against peers, before any relative-valuation take.","path_params":["ticker"],"query_params":[{"name":"limit","type":"int","default":10,"min":1,"max":50},{"name":"min_relative_size","type":"float","default":0.1,"min":0.0,"max":1.0,"description":"Keep peers at least this FRACTION of the company's size (TTM revenue; total assets for a bank or broker), 0.10 = 10%. The default steps down to 0.05, 0.02 and 0.01 when fewer than `limit` clear it; any other value is applied as given. 0 keeps every peer."}],"admin":false,"display_name":"Sector peers","public_name":"fundamentals_peers"},{"name":"tengu_v3_fundamentals_search","method":"GET","path":"/api/v3/fundamentals/search","group":"v3","description":"Fuzzy company lookup — resolves a free-text name or partial ticker to matching companies (default 10). Call it FIRST when the user names a company without a ticker, before firing any ticker-keyed fundamentals tool. Each row carries is_active and listing_status from the security master (active; renamed with now_trades_as; delisted with delist_date, from the master's own delisting record; not_current_symbol; not_in_security_master; identity_unconfirmed when the master's current security under the symbol is another company; or unchecked when the master could not be read, is_active null), judged first on the row's company name, then, when no name decides, a current listing over a delisted holder of the spelling (BRKB is Berkshire, not Brooklyn Bancorp); delisted names are included but ranked after active ones. The status read waits at most 4.5 s on an uncached symbol and is skipped for 30 s after the master fails (rows then unchecked).","query_params":[{"name":"q","type":"string","required":true},{"name":"limit","type":"int","default":10,"min":1,"max":50}],"admin":false,"display_name":"Ticker search","public_name":"fundamentals_search"},{"name":"tengu_v3_fundamentals_tickers","method":"GET","path":"/api/v3/fundamentals/tickers","group":"v3","description":"Paged listing of the full covered ticker universe, filterable to S&P 500 membership or one sector (limit/page paging: page counts pages of limit rows, up to 500). The response carries total, has_more, next_page and truncated; keep paging while has_more is true. A page the source fails on is a 503 upstream_unavailable, never a shorter list. Call it when the user wants all the stocks in a sector or an index-membership list to feed a screen.","query_params":[{"name":"is_sp500","type":"bool","default":false},{"name":"sector","type":"string"},{"name":"limit","type":"int","default":100,"min":1,"max":500},{"name":"page","type":"int","default":1,"min":1,"max":200}],"admin":false,"display_name":"Ticker list","public_name":"fundamentals_tickers"},{"name":"tengu_v3_fundamentals_screener","method":"GET","path":"/api/v3/fundamentals/screener","group":"v3","description":"Multi-filter stock screener combining profitability (ROE, ROA, net margin), growth (revenue, EPS), financial-health (debt/equity, current ratio) and dividend filters, with sector/industry scoping. Results are sized, floored and sorted on our own data: market_cap_usd and adv_21d_usd from exchange prices and shares outstanding, common equity only unless security_class asks for more, and revenue_usd / net_income_usd only where the reporting currency is established (raw revenue stays in the issuer's own currency and is not comparable across rows). Default floors: $300M market cap and $1M/day dollar volume. The response carries field_sources and as_of; liquid listings the market-cap floor dropped for lack of a verifiable size are named in universe.liquid_without_market_cap, and a row still filed under a symbol its issuer retired in the last 18 months is sized on the current listing (listing_ticker). market_cap_usd is null when the close moved more than 3x (either way) from the split-adjusted close on the share count's own date, genuine moves included: the count is not trusted; such rows leave floored screens and, when they trade at least $1M a day, are named with the reason. While its size data warms on a fresh server it returns 503 build_timeout with Retry-After; when that data or the fundamentals source cannot be read it returns 503 upstream_unavailable (error_code screener_size_data_unavailable or screener_vendor_unavailable; refunded), never an empty list. PRIMARY tool for 'find me stocks that…' asks; ready-made strategies live in /fundamentals/screener/presets. UNITS: filters ending in _pct are PERCENT numbers (roe_min_pct=20 means ROE >= 20%, and 0.5 means 0.5%); the older names (roe_min, revenue_growth_min, ...) are the same percent unit and refuse a value between -1 and 1 as ambiguous (422 ambiguous_percent_threshold, refunded). debt_to_equity_max and current_ratio_min are MULTIPLES (0.5 = 0.5x). Row ratios, margins, growth and payout are percent numbers and debt_to_equity / current_ratio / quick_ratio multiples, for each row's latest fiscal year (fiscal_year), not TTM; the response states every filter it applied with its unit (filters_applied) and every field's unit (units). Rows with negative equity carry equity_negative and never pass a D/E ceiling. Revenue growth beyond +-100% is checked against the issuer's SEC annual report (growth_status, revenue_growth_basis; the vendor's figure stays in vendor_revenue_growth_yoy) and the growth filter is applied again to the checked figure; a company the source excluded on a wrong figure cannot be recovered. Over MCP an argument this tool does not declare is refused with the accepted list, never ignored. gross_margin_min_pct, operating_margin_min_pct (percent) and revenue_min_usd / revenue_max_usd (USD, on revenue_usd) are applied by this screener to the served rows, after the source's filters; a row without the figure does not pass, and local_filters echoes them.","reject_unknown_args":true,"query_params":[{"name":"sector","type":"string","description":"The source's sector name, e.g. Technology, Healthcare, Financial Services."},{"name":"industry","type":"string","description":"The source's industry name, e.g. Semiconductors, Insurance - Property & Casualty."},{"name":"roe_min_pct","type":"float","description":"Minimum return on equity in PERCENT: 20 keeps ROE >= 20%; 0.5 keeps ROE >= 0.5%. Each row's latest fiscal year (not TTM): net income / average shareholders' equity."},{"name":"roe_max_pct","type":"float","description":"Maximum return on equity in PERCENT: 50 keeps ROE <= 50%. Latest fiscal year, net income / average shareholders' equity."},{"name":"roa_min_pct","type":"float","description":"Minimum return on assets in PERCENT: 10 keeps ROA >= 10%. Latest fiscal year, net income / total assets at year end."},{"name":"net_margin_min_pct","type":"float","description":"Minimum net margin in PERCENT: 15 keeps net income / revenue >= 15%. Latest fiscal year."},{"name":"revenue_growth_min_pct","type":"float","description":"Minimum revenue growth vs the prior fiscal year in PERCENT: 20 keeps growth >= 20%; -10 admits declines of up to 10%. Latest fiscal year. Growth beyond +-100% is checked against the SEC annual report and this floor is applied again to the checked figure."},{"name":"eps_growth_min_pct","type":"float","description":"Minimum diluted-EPS growth vs the prior fiscal year in PERCENT: 25 keeps EPS growth >= 25%. Latest fiscal year."},{"name":"payout_ratio_max_pct","type":"float","description":"Maximum payout ratio in PERCENT: 60 keeps dividends paid / net income <= 60%. Latest fiscal year."},{"name":"gross_margin_min_pct","type":"float","description":"Minimum gross margin in PERCENT (40 = 40%), latest fiscal year. Applied by this screener to the served rows; a row without it does not pass."},{"name":"operating_margin_min_pct","type":"float","description":"Minimum operating margin in PERCENT, latest fiscal year. Applied by this screener to the served rows."},{"name":"revenue_min_usd","type":"float","description":"Minimum revenue in USD (revenue_usd, latest fiscal year). A row whose USD revenue is not established does not pass."},{"name":"revenue_max_usd","type":"float","description":"Maximum revenue in USD (revenue_usd, latest fiscal year). A row whose USD revenue is not established does not pass."},{"name":"gross_margin_min","type":"float","description":"Alias of gross_margin_min_pct (PERCENT); a value between -1 and 1 is refused as ambiguous (422)."},{"name":"operating_margin_min","type":"float","description":"Alias of operating_margin_min_pct (PERCENT); a value between -1 and 1 is refused as ambiguous (422)."},{"name":"revenue_min","type":"float","description":"Alias of revenue_min_usd (USD)."},{"name":"revenue_max","type":"float","description":"Alias of revenue_max_usd (USD)."},{"name":"roe_min","type":"float","description":"Deprecated: same as roe_min_pct, in PERCENT (20 = 20%). A value strictly between -1 and 1 other than 0 is refused as ambiguous (422 ambiguous_percent_threshold); roe_min_pct is never refused for size."},{"name":"roe_max","type":"float","description":"Deprecated: same as roe_max_pct, in PERCENT (50 = 50%). Values strictly between -1 and 1 other than 0 are refused as ambiguous (422)."},{"name":"roa_min","type":"float","description":"Deprecated: same as roa_min_pct, in PERCENT (10 = 10%). Values strictly between -1 and 1 other than 0 are refused as ambiguous (422)."},{"name":"net_margin_min","type":"float","description":"Deprecated: same as net_margin_min_pct, in PERCENT (15 = 15%). Values strictly between -1 and 1 other than 0 are refused as ambiguous (422)."},{"name":"revenue_growth_min","type":"float","description":"Deprecated: same as revenue_growth_min_pct, in PERCENT (20 = 20%). Values strictly between -1 and 1 other than 0 are refused as ambiguous (422)."},{"name":"eps_growth_min","type":"float","description":"Deprecated: same as eps_growth_min_pct, in PERCENT (25 = 25%). Values strictly between -1 and 1 other than 0 are refused as ambiguous (422)."},{"name":"debt_to_equity_max","type":"float","description":"Maximum total debt / shareholders' equity as a MULTIPLE, not a percent: 0.5 keeps debt <= half of equity, 1 keeps debt <= equity. 0 to 20, else 422 debt_to_equity_max_out_of_range. Latest fiscal year end. Companies with negative equity (negative D/E, equity_negative) never pass."},{"name":"current_ratio_min","type":"float","description":"Minimum current assets / current liabilities as a MULTIPLE: 1.5 keeps a current ratio >= 1.5x. Latest fiscal year end."},{"name":"years_dividend_growth_min","type":"int","description":"Minimum consecutive years of dividend-per-share growth, in YEARS: 10 keeps streaks of 10 or more."},{"name":"payout_ratio_max","type":"float","description":"Deprecated: same as payout_ratio_max_pct, in PERCENT (60 = 60%). Values strictly between -1 and 1 other than 0 are refused as ambiguous (422)."},{"name":"sort_by","type":"string","default":"market_cap_usd","enum":["market_cap_usd","adv_21d_usd","price_usd","revenue_usd","net_income_usd","revenue_growth_yoy","net_income_growth_yoy","eps_growth_yoy","roe","roa","gross_margin","operating_margin","net_margin","debt_to_equity","current_ratio","quick_ratio","payout_ratio","dividend_growth_yoy","years_dividend_growth","market_cap","marketcap","revenue","net_income","adv","adv_21d","adv_usd","dollar_volume","price","revenue_growth","eps_growth","net_income_growth","dividend_growth"],"description":"Sorted over the whole matched set, nulls last. The short spellings are aliases: market_cap/marketcap -> market_cap_usd, revenue -> revenue_usd, net_income -> net_income_usd, adv/adv_21d/adv_usd/dollar_volume -> adv_21d_usd, price -> price_usd, and *_growth -> *_growth_yoy. revenue and net_income sort in USD, never on the issuer's own currency. Any other key is a 400 listing the allowed ones."},{"name":"sort_order","type":"string","default":"desc","enum":["asc","desc"],"description":"desc (default) or asc; rows without a value sort last either way."},{"name":"limit","type":"int","default":50,"min":1,"max":100,"description":"Rows per page, 1 to 100."},{"name":"page","type":"int","default":1,"min":1,"max":100,"description":"Page of the whole matched and sorted set, from 1."},{"name":"min_market_cap_usd","type":"float","default":300000000,"min":0,"max":1000000000000,"description":"Issuer market-cap floor, USD. 0 disables it and also admits rows whose market cap is unknown (ADRs, funds)."},{"name":"min_adv_usd","type":"float","default":1000000,"min":0,"max":10000000000,"description":"Floor on 21-session average daily dollar volume, USD. 0 disables it."},{"name":"security_class","type":"string","default":"common","description":"Comma list of classes to include: common, adr, preferred, fund, unit, warrant, other. Unknown classes are a 400."}],"admin":false,"display_name":"Stock screener","public_name":"fundamentals_screener"},{"name":"tengu_v3_fundamentals_screener_presets","method":"GET","path":"/api/v3/fundamentals/screener/presets","group":"v3","description":"Catalog of pre-built screener strategies — Aristocrats, Cash Cows, Value, Quality and more. Call it when the user asks for a named strategy screen or wants screening ideas before composing /fundamentals/screener filters. Each preset's params are restated in this screener's own parameter names (roe_min_pct, gross_margin_min_pct, revenue_max_usd, ...), so every filter it names is applied; vendor_params keeps the source's string, and supported/unsupported_params flag any it cannot run. 'Dividend Growers (10y+)' is the source's 'Dividend Aristocrats' (10+ years, not the S&P index's 25+).","admin":false,"display_name":"Strategy screens","public_name":"fundamentals_screener_presets"},{"name":"tengu_v3_fundamentals_ai_analyze","method":"GET","path":"/api/v3/fundamentals/ai_analyze/{ticker}","group":"v3","description":"AI-generated company analysis for one ticker — summary, strengths, concerns, peer comparison and a quality score. Call this when the user wants a synthesized qualitative read rather than raw numbers. Pro and above, 6 credits a call. The text is the source's model output (is_model_output true): check quoted figures against fundamentals_metrics_snapshot. When the source fails it returns 503 upstream_unavailable (error_code ai_analyze_vendor_error; not billed), never an empty analysis; when the source has no analysis for the symbol it returns 404 no_analysis_available (not billed). A symbol the platform does not know at all, current or delisted, is refused 404 unknown_ticker (not billed). Each customer gets 3 new analyses a day (UTC), across all its keys, and new analyses stop for the month once the monthly allowance is used: both refusals are a 503 (daily_limit_reached, quota_exhausted) with Retry-After and are not billed. A ticker analysed in the last 24 hours answers from cache and counts against neither limit.","path_params":["ticker"],"admin":false,"display_name":"Filings analysis","public_name":"fundamentals_ai_analyze"},{"name":"tengu_v3_fundamentals_historical","method":"GET","path":"/api/v3/fundamentals/historical/{ticker}","group":"v3","description":"Multi-decade historical financial statements for one ticker from SEC EDGAR — income, balance, and cash-flow, filterable by statement_type and start_year/end_year, annual by default with include_quarterly opt-in. Years are FISCAL years; with no end_year the range runs to next calendar year, so the latest fiscal year is included (NVDA's FY2027 ends in January 2027). Call this when the user asks how fundamentals have trended over many years, not just the latest print.","path_params":["ticker"],"query_params":[{"name":"statement_type","type":"string","default":"all","enum":["income","balance","cashflow","all"]},{"name":"start_year","type":"int","min":1990,"max":2100},{"name":"end_year","type":"int","min":1990,"max":2100},{"name":"include_quarterly","type":"bool","default":false}],"admin":false,"display_name":"Financial history","public_name":"fundamentals_historical"},{"name":"tengu_v3_intel_options_flow","method":"GET","path":"/api/v3/intel/options_flow","group":"v3","description":"The most recent unusual options-flow alerts across the whole market from the options-flow feed with premium at or above min_premium (default $50k), newest first, at most limit. scan says how many alerts the feed returned and the window of alert times they cover (a busy session fills limit within minutes). executed_at is the alert's last print (executed_at_basis says when only the later alert time was available). Call this when the user asks 'what is the smart money buying today?' or wants market-wide unusual options activity; use tengu_v3_intel_options_flow_ticker for a single name.","query_params":[{"name":"freshness","type":"string","default":"off","enum":["off","live","strict"],"description":"Freshness policy. 'off' serves with an age footnote; 'live'/'strict' return 503 data_stale rather than serve stale data"},{"name":"limit","type":"int","default":50,"min":1,"max":200,"description":"max qualifying alerts returned, newest first"},{"name":"min_premium","type":"int","default":50000,"min":0,"max":100000000,"description":"USD premium floor per alert"}],"admin":false,"display_name":"Options flow (recent)","public_name":"intel_options_flow"},{"name":"tengu_v3_intel_options_flow_ticker","method":"GET","path":"/api/v3/intel/options_flow/{ticker}","group":"v3","description":"Unusual options-flow alerts for one ticker from the options-flow feed (default 25), newest first; executed_at is the alert's last print (executed_at_basis says when only the later alert time was available). An unknown symbol is a 404. Call this when the user asks 'any unusual options activity in X?' or wants the large options bets hitting a specific name; use tengu_v3_intel_options_flow for the cross-market view.","path_params":["ticker"],"query_params":[{"name":"freshness","type":"string","default":"off","enum":["off","live","strict"],"description":"Freshness policy. 'off' serves with an age footnote; 'live'/'strict' return 503 data_stale rather than serve stale data"},{"name":"limit","type":"int","default":25,"min":1,"max":200}],"admin":false,"display_name":"Options flow (ticker)","public_name":"intel_options_flow_ticker"},{"name":"tengu_v3_intel_darkpool_recent","method":"GET","path":"/api/v3/intel/darkpool/recent","group":"v3","description":"Most recent dark-pool prints across all tickers from the options-flow feed (default 50): size, price, notional, executed_at, market_center (the facility that reported the print), the NBBO at the print, and the feed's condition codes (extended_hours_code, sale_condition_code, settlement); exchange is null by construction, because these prints did not execute on an exchange. Call this when the user asks about market-wide dark-pool or block activity — 'any big dark-pool prints today?'; use tengu_v3_intel_darkpool_ticker for a single name.","query_params":[{"name":"freshness","type":"string","default":"off","enum":["off","live","strict"],"description":"Freshness policy. 'off' serves with an age footnote; 'live'/'strict' return 503 data_stale rather than serve stale data"},{"name":"limit","type":"int","default":50,"min":1,"max":200}],"admin":false,"display_name":"Dark pool prints (recent)","public_name":"intel_darkpool_recent"},{"name":"tengu_v3_intel_darkpool_ticker","method":"GET","path":"/api/v3/intel/darkpool/{ticker}","group":"v3","description":"Dark-pool prints for one ticker from the options-flow feed (default 50), with the same fields as tengu_v3_intel_darkpool_recent (market_center, NBBO, condition codes; exchange is null because the prints are off-exchange). Call this when the user asks whether large blocks are crossing off-exchange in a specific name; use tengu_v3_intel_off_exchange for daily aggregate off-exchange volume instead of individual prints.","path_params":["ticker"],"query_params":[{"name":"freshness","type":"string","default":"off","enum":["off","live","strict"],"description":"Freshness policy. 'off' serves with an age footnote; 'live'/'strict' return 503 data_stale rather than serve stale data"},{"name":"limit","type":"int","default":50,"min":1,"max":200}],"admin":false,"display_name":"Dark pool prints (ticker)","public_name":"intel_darkpool_ticker"},{"name":"tengu_v3_intel_gex","method":"GET","path":"/api/v3/intel/gex/{ticker}","group":"v3","description":"Aggregate gamma exposure (GEX) and delta exposure for one ticker from the options-flow feed. Call this when the user asks about dealer positioning or gamma levels, or whether options exposure could dampen or amplify moves in a name; pair with tengu_v3_intel_max_pain for expiry pin levels. UNITS: call_gamma/put_gamma are SHARES of underlying per $1 move (sum of gamma x open interest x 100; calls positive, puts negative by the dealer convention), NOT dollars; gamma_usd_per_1pct_move gives the dollar GEX per 1% move (x spot^2 x 0.01) with its spot. Deltas are shares (delta x OI x 100). Share figures scale with the square of a split ratio; the dollar figure does not. The units block in the response states all of this.","path_params":["ticker"],"query_params":[{"name":"freshness","type":"string","default":"off","enum":["off","live","strict"],"description":"Freshness policy. 'off' serves with an age footnote; 'live'/'strict' return 503 data_stale rather than serve stale data"}],"admin":false,"display_name":"Gamma exposure","public_name":"intel_gex"},{"name":"tengu_v3_intel_max_pain","method":"GET","path":"/api/v3/intel/max_pain/{ticker}","group":"v3","description":"Max-pain price per options expiration for one ticker from the options-flow feed, with the underlying's latest price (underlying_price, underlying_as_of; each row's spot). Call this when the user asks where a stock is likely to pin into expiry or what the max-pain level is; pair with tengu_v3_intel_gex for aggregate gamma/delta exposure.","path_params":["ticker"],"admin":false,"display_name":"Max pain","public_name":"intel_max_pain"},{"name":"tengu_v3_intel_options_volume","method":"GET","path":"/api/v3/intel/options_volume/{ticker}","group":"v3","description":"Daily options volume and put/call ratio per day for one ticker from the options-flow feed (default 30 days). Call this when the user asks whether options activity or put/call skew is elevated versus recent days, or how bullish/bearish the options tape has been trending. The newest row can be today's session still trading: it then carries session_complete false and as_of_ts, and its totals run only to that time, so do not compare it with a full day. put_call_ratio is null, with a reason, when there was no call volume.","path_params":["ticker"],"query_params":[{"name":"limit","type":"int","default":30,"min":1,"max":200}],"admin":false,"display_name":"Options volume","public_name":"intel_options_volume"},{"name":"tengu_v3_intel_factor_importance","method":"GET","path":"/api/v3/intel/factor_importance","group":"v3","description":"What drives the model: Fama-French 5-factor loadings showing which systematic factors explain the strategy's returns, plus the ensemble's Bayesian voter posteriors ranking which signals it trusts most (top_n, default 50). PRIMARY tool for 'why does the model like this?' and 'what is the strategy actually betting on?' questions. Each report's as_of and `stale` flag are in `report_freshness`.","query_params":[{"name":"top_n","type":"int","default":50,"min":1,"max":500}],"admin":false,"public_name":"intel_factor_importance"},{"name":"tengu_v3_risk_historical_var_scenario","method":"POST","path":"/api/v3/risk/historical_var_scenario","group":"v3","description":"Empirical historical VaR and expected shortfall for an explicit user-supplied USD equity portfolio. Uses bounded daily total returns and non-overlapping horizon scenarios. Requires at least ten tail observations. Discloses input provenance and window age. Research only; does not verify account holdings, calibrate future coverage, or authorize trades.","body_schema":{"$defs":{"EquityExposure":{"additionalProperties":false,"properties":{"permno":{"exclusiveMinimum":0,"maximum":99999999,"title":"Permno","type":"integer"},"asset_class":{"const":"equity","default":"equity","title":"Asset Class","type":"string"},"currency":{"const":"USD","default":"USD","title":"Currency","type":"string"},"side":{"enum":["long","short"],"title":"Side","type":"string"},"market_value_usd":{"exclusiveMinimum":0,"maximum":1000000000000.0,"title":"Market Value Usd","type":"number"}},"required":["permno","side","market_value_usd"],"title":"EquityExposure","type":"object"},"PortfolioSnapshot":{"additionalProperties":false,"properties":{"snapshot_id":{"maxLength":128,"minLength":1,"title":"Snapshot Id","type":"string"},"as_of":{"format":"date-time","title":"As Of","type":"string"},"currency":{"const":"USD","default":"USD","title":"Currency","type":"string"},"nav_usd":{"exclusiveMinimum":0,"maximum":1000000000000.0,"title":"Nav Usd","type":"number"},"cash_usd":{"maximum":1000000000000.0,"minimum":-1000000000000.0,"title":"Cash Usd","type":"number"},"positions":{"items":{"$ref":"#/$defs/EquityExposure"},"maxItems":20,"minItems":1,"title":"Positions","type":"array"}},"required":["snapshot_id","as_of","nav_usd","cash_usd","positions"],"title":"PortfolioSnapshot","type":"object"},"ReturnSeries":{"additionalProperties":false,"properties":{"permno":{"exclusiveMinimum":0,"maximum":99999999,"title":"Permno","type":"integer"},"values":{"items":{"minimum":-1,"type":"number"},"maxItems":2520,"minItems":1,"title":"Values","type":"array"}},"required":["permno","values"],"title":"ReturnSeries","type":"object"},"SuppliedHistory":{"additionalProperties":false,"properties":{"kind":{"const":"supplied_total_returns","title":"Kind","type":"string"},"source_label":{"maxLength":128,"minLength":1,"title":"Source Label","type":"string"},"return_basis":{"const":"total_return_including_distributions_and_delisting","title":"Return Basis","type":"string"},"dates":{"items":{"format":"date","type":"string"},"maxItems":2520,"minItems":1,"title":"Dates","type":"array"},"series":{"items":{"$ref":"#/$defs/ReturnSeries"},"maxItems":20,"minItems":1,"title":"Series","type":"array"}},"required":["kind","source_label","return_basis","dates","series"],"title":"SuppliedHistory","type":"object"},"WarehouseHistory":{"additionalProperties":false,"properties":{"kind":{"const":"warehouse_crsp","title":"Kind","type":"string"},"start":{"format":"date","title":"Start","type":"string"},"end":{"format":"date","title":"End","type":"string"}},"required":["kind","start","end"],"title":"WarehouseHistory","type":"object"}},"additionalProperties":false,"properties":{"portfolio":{"$ref":"#/$defs/PortfolioSnapshot"},"history":{"discriminator":{"mapping":{"supplied_total_returns":"#/$defs/SuppliedHistory","warehouse_crsp":"#/$defs/WarehouseHistory"},"propertyName":"kind"},"oneOf":[{"$ref":"#/$defs/WarehouseHistory"},{"$ref":"#/$defs/SuppliedHistory"}],"title":"History"},"confidence":{"default":0.95,"maximum":0.99,"minimum":0.9,"title":"Confidence","type":"number"},"horizon_sessions":{"default":1,"maximum":30,"minimum":1,"title":"Horizon Sessions","type":"integer"}},"required":["portfolio","history"],"title":"HistoricalVarRequest","type":"object"},"capability_tags":["heavy"],"admin":false,"public_name":"tengu_v3_risk_historical_var_scenario"},{"name":"tengu_v3_research_correlation_mesh","method":"GET","path":"/api/v3/research/correlation_mesh","group":"v3","description":"Returns-correlation mesh around a seed ticker — nodes = tickers, edges = |rho| >= 0.6 on monthly returns over the last 36 months (depth expands the neighborhood). PRIMARY tool for 'what moves with X?' and finding hedge or pair candidates. Every edge shares at least 34 of the window's 36 months (n_overlap_months); series that stopped trading before the seed's latest month are excluded, and `window` gives the months used. Nodes can be ETFs and funds as well as companies (no instrument-type filter). A seed outside the correlation universe (fewer than 34 monthly returns in the window) is 404 seed_not_in_universe, and a symbol neither the market-data listing nor the security master knows is 404 unknown_ticker. While the returns data loads on a server the answer is a 503 build_timeout with Retry-After; if it cannot load, 503 corr_cache_warming. None is billed.","query_params":[{"name":"seed","type":"string","required":true},{"name":"depth","type":"int","default":1,"min":1,"max":3}],"capability_tags":["heavy"],"admin":false,"public_name":"research_correlation_mesh"},{"name":"tengu_v3_intel_insider_trades","method":"GET","path":"/api/v3/intel/insider_trades/{ticker}","group":"v3","description":"SEC Form 4 insider trades for one ticker — recent buys and sells by officers, directors, and large holders (default 25). Call this when the user asks 'are insiders buying or selling X?' or wants to check insider conviction before acting on a name. items holds executed transactions only, each with its form, the Rule 10b5-1 flag (is_10b5_1), direct/indirect ownership and the security title (null when the feed does not state one). Form 144 notices of a PROPOSED sale are never items: they are listed apart under intent_to_sell_notices and belong in no sale total, so count can be below limit. price is as filed, in the filing's currency; value and proposed_sale_value_usd are null with a *_reason where it is not known to be dollars (an ADR's filings are home-market shares; a foreign issuer with a listing in Canada may file at the Canadian price). An unknown symbol is a 404 unknown_ticker.","path_params":["ticker"],"query_params":[{"name":"limit","type":"int","default":25,"min":1,"max":200}],"admin":false,"display_name":"Insider trades (newswire)","public_name":"intel_insider_trades"},{"name":"tengu_v3_intel_congress","method":"GET","path":"/api/v3/intel/congress","group":"v3","description":"Congressional trades from two coverage sources — a realtime cross-ticker feed (provider=options_flow, default) or a bulk alternative-data feed (provider=alternative_data) — with an optional ticker filter, each trade with the member's party (null when unknown). With provider=alternative_data and a ticker, trades come from a warehouse copy that holds trades from 2025-05-20 onward (earlier history for 114 tickers); data_from, history_floor and coverage_note say where the copy begins, so never call it the complete history. Both feeds add side (buy/sell/exchange), party_code, chamber_code and is_member_of_congress (false for an executive-branch filer), and owner (whose account: self, spouse, joint, child) where the feed states it. On options_flow each trade also carries asset_type (stock, option, government_security, ...) from the disclosure's asset code, and an option row's side is the side of the option trade (side_applies_to option_contract; option_type, strike and expiry only where the source states them); a House member's own account reads owner self (owner_basis). reported_date_basis says what reported_date is: on options_flow it is the day the source recorded the disclosure, which can trail the filing date by one to three days. Call this when the user asks what Congress members have been buying or selling, market-wide or in a specific name. A 503 means the feed could not be read, not that nobody traded; a ticker the security master does not carry is a 404 unknown_ticker.","query_params":[{"name":"ticker","type":"string"},{"name":"limit","type":"int","default":50,"min":1,"max":500},{"name":"provider","type":"string","default":"options_flow","enum":["options_flow","alternative_data"]}],"admin":false,"display_name":"Congressional trades","public_name":"intel_congress"},{"name":"tengu_v3_intel_lobbying","method":"GET","path":"/api/v3/intel/lobbying/{ticker}","group":"v3","description":"Corporate lobbying filings for one ticker, newest first (client, registrant, amount, issues, filing date; limit, default 50), from the warehouse copy of the alternative-data feed with its own clocks (as_of, data_through). The copy holds filings from 2025-01-19 onward; older filings may exist upstream and are NOT included (data_from, history_floor, coverage_note). A filing with no amount (a registration, or a report under $5,000) has amount null and amount_reason. amount_basis says whether an amount is the company's own in-house lobbying expenses, which already include outside firms' fees, or an outside firm's income from it: do not add the two. Call this when the user asks how much a company spends lobbying or whether its policy exposure is growing; pair with tengu_v3_intel_gov_contracts for the government-contract side of the same story. A 503 means the data could not be retrieved, not that the company does no lobbying; an unknown symbol is a 404 unknown_ticker.","path_params":["ticker"],"query_params":[{"name":"limit","type":"int","default":50,"min":1,"max":500}],"admin":false,"display_name":"Lobbying activity","public_name":"intel_lobbying"},{"name":"tengu_v3_intel_gov_contracts","method":"GET","path":"/api/v3/intel/gov_contracts/{ticker}","group":"v3","description":"Federal contract awards to one ticker's company as QUARTERLY TOTALS (not individual awards) on the US federal fiscal year — Q1 is October-December, and each item carries period_start/period_end — from the warehouse copy of the alternative-data feed (as_of is its last snapshot; history from FY2020 Q2; limit, default 50). The newest quarter may still be in progress, and recent quarters keep growing for months as awards are reported. Call this when the user asks how much government business a company wins or whether contract awards are accelerating; pair with tengu_v3_intel_lobbying for the lobbying-spend side. A 503 means the data could not be retrieved, not that the company has no contracts; an unknown symbol is a 404 unknown_ticker.","path_params":["ticker"],"query_params":[{"name":"limit","type":"int","default":50,"min":1,"max":500}],"admin":false,"display_name":"Government contracts","public_name":"intel_gov_contracts"},{"name":"tengu_v3_intel_wsb","method":"GET","path":"/api/v3/intel/wsb/{ticker}","group":"v3","description":"Daily r/wallstreetbets mention count and sentiment for one ticker from the alternative-data feed, newest day first (limit rows, default 60, one per day with data); newest_date and oldest_date bound the rows served, so check newest_date before calling the buzz current. An unknown symbol is a 404 unknown_ticker. Call this when the user asks whether retail is piling into a name or how retail buzz is trending; pair with tengu_v3_intel_twitter for the Twitter-side social read.","path_params":["ticker"],"query_params":[{"name":"limit","type":"int","default":60,"min":1,"max":365}],"admin":false,"display_name":"Retail chatter","public_name":"intel_wsb"},{"name":"tengu_v3_intel_twitter","method":"GET","path":"/api/v3/intel/twitter/{ticker}","group":"v3","description":"Daily Twitter mention volume and follower count for one ticker from the alternative-data feed (default 60 days). The upstream dataset returned no rows for any ticker when checked on 2026-07-02 and 2026-09-24, so this answers 503 upstream_dataset_empty until it recovers; prefer tengu_v3_intel_wsb for retail attention.","path_params":["ticker"],"query_params":[{"name":"limit","type":"int","default":60,"min":1,"max":365}],"admin":false,"display_name":"Twitter mentions","public_name":"intel_twitter"},{"name":"tengu_v3_intel_off_exchange","method":"GET","path":"/api/v3/intel/off_exchange/{ticker}","group":"v3","description":"Daily off-exchange (dark pool + ATS) volume for one ticker, newest session first (default 30 rows), from the warehouse copy of the alternative-data feed, which holds sessions from 2026-05-08: off_exchange_volume, short_volume and short_volume_share (short_volume / off_exchange_volume as a fraction, the short-sale share of OFF-EXCHANGE volume, not the share of all volume that trades off-exchange). dark_pool_pct is null and total_volume is null: the feed carries no consolidated volume, so the off-exchange share of total volume is not served here. The copy misses some sessions: missing_sessions lists the trading sessions inside the served span it lacks, and /origin/short_activity serves the regulator's daily file for up to the last 60 sessions. Call this when the user asks how much a stock trades off-exchange or how short selling off-exchange is trending; use tengu_v3_intel_darkpool_ticker for individual prints. A 503 means the data could not be retrieved, not that there was no off-exchange volume.","path_params":["ticker"],"query_params":[{"name":"freshness","type":"string","default":"off","enum":["off","live","strict"],"description":"Freshness policy. 'off' serves with an age footnote; 'live'/'strict' return 503 data_stale rather than serve stale data"},{"name":"limit","type":"int","default":30,"min":1,"max":200}],"admin":false,"display_name":"Off-exchange flow","public_name":"intel_off_exchange"},{"name":"tengu_v3_intel_patents","method":"GET","path":"/api/v3/intel/patents/{ticker}","group":"v3","description":"Issued USPTO patents tagged to one ticker — date, title, IPC class, claim count, and abstract for each (default 25) — from a warehouse copy loaded once (as_of) for a watchlist of 71 tickers; it holds a recent window per ticker, so data_from and coverage_note say where this ticker's copy begins. Other tickers use the live feed. Call this when the user asks what a company is patenting or wants an innovation-velocity read on its R&D pipeline. A 503 means the data could not be retrieved, not that the company holds no patents; an unknown symbol is a 404 unknown_ticker.","path_params":["ticker"],"query_params":[{"name":"limit","type":"int","default":25,"min":1,"max":200}],"admin":false,"display_name":"Patents","capability_tags":["heavy"],"public_name":"intel_patents"},{"name":"tengu_v3_intel_chart","method":"GET","path":"/api/v3/intel/chart/{ticker}","group":"v3","description":"Candlestick chart with optional RSI/MACD/Bollinger overlays — returns a base64 PNG in a standard image envelope plus an OHLCV summary block (interval minute|hour|day|week|month, default day; 120 bars). Minute and hour charts include today's session, extended hours too (last_bar_session); day charts end at the last completed session. A forming bar is flagged (last_bar_is_partial) and current_price_basis says whether the price is a completed bar's close or the latest trade. SMA 20/50/200 and ATR 14 (Wilder) use the full fetched history; week52_high/low span 52 weeks of daily sessions (week52_window), not the bars drawn. An unknown symbol is a 404 unknown_ticker. Call this when the user asks to see a chart; powers chart-emitting skills (TA Master, Trading Plan, Apex Equity Intel).","path_params":["ticker"],"query_params":[{"name":"interval","type":"string","default":"day","enum":["minute","hour","day","week","month"],"description":"minute|hour|day|week|month"},{"name":"bars","type":"int","default":120,"min":20,"max":500},{"name":"indicators","type":"string","default":"rsi,macd,bb","description":"Comma-separated subset of {rsi,macd,bb}"}],"admin":false,"display_name":"Price chart","public_name":"intel_chart"},{"name":"tengu_v3_intel_insiders","method":"GET","path":"/api/v3/intel/insiders","group":"v3","description":"Live cross-ticker Form-4 insider-transaction feed (alternative-data, last ~20k rows): name, transaction_code, shares, price_per_share, value_usd, shares_owned_following, filing_date, ownership. Call this when the user asks 'are insiders buying or selling?' — one name or market-wide. Optional ticker filter is applied client-side to that page, so a per-ticker answer covers only feed_window (rows_scanned, window_start, window_end), not the company's history; tengu_v3_intel_insider_flow reads the full archive. price_per_share is as filed, in the filing's currency: value_usd is null with value_usd_reason on any row not known to be in dollars (an ADR's home-market shares, a foreign issuer with a listing in Canada, a ticker the security master does not place).","query_params":[{"name":"ticker","type":"string","description":"Optional ticker filter"},{"name":"limit","type":"int","default":50,"min":1,"max":500}],"admin":false,"display_name":"Insider activity","public_name":"intel_insiders"},{"name":"tengu_v3_intel_sec13f","method":"GET","path":"/api/v3/intel/sec13f","group":"v3","description":"13F position snapshots from the institutional 13F archive: fund, ticker, shares, value_usd, report_period — the institutional-ownership signal. Call this when the user asks 'which funds hold X?' or 'what does fund Y own?'; filter by ticker and/or fund (substring match). The archive ends a quarter behind EDGAR: answers carry newest_report_period, vendor_ceiling, expected_report_period, is_stale and quarters_behind. A ticker is read on its share class's CUSIP (security_key; GOOGL and GOOG are separate). missing_known_filers and coverage_note name manager families whose 13F filings the archive does not carry for the quarter (Vanguard's successor filers from 2026-03-31), so their positions are absent, not sold. fund is the archive's manager label; fund_current_name gives today's name where the label is a former one (manager_name_note). For a ticker, current_quarter adds the newer EDGAR 13F filings of the tracked managers only (coverage 'tracked_managers_only', report_period on each item); it is not the full holder list. current_quarter_error says those filings could not be read. Alternative-data rows served because the archive could not be read carry archive_error; fallback rows are the filings it has indexed, not a full holder list (coverage_note). When neither source can answer the route returns 503 upstream_unavailable (error_code archive_read_timeout, archive_read_failed or upstream_dead_no_archive; not billed), never an empty list.","query_params":[{"name":"ticker","type":"string"},{"name":"fund","type":"string","description":"Substring match on fund name"},{"name":"limit","type":"int","default":50,"min":1,"max":500}],"admin":false,"display_name":"Institutional holdings","capability_tags":["heavy"],"public_name":"intel_sec13f"},{"name":"tengu_v3_intel_sec13f_changes","method":"GET","path":"/api/v3/intel/sec13f/changes","group":"v3","description":"Quarter-over-quarter 13F position deltas from the institutional 13F archive, sign preserved: positive = added, negative = trimmed. Call this when the user asks 'are institutions adding or dumping X?'; set min_pct (absolute change fraction, e.g. 0.5 = 50%) to drop noise. A change needs a filing in both quarters: a manager with no filing at all in the newer quarter is not shown as a seller (unreported_prev_holders counts them), nor one with none in the older quarter as a buyer (unreported_cur_holders). Across a stock split the earlier quarter is put on the later quarter's share basis (prev_shares_split_factor, split_adjustment); a change the split alone would explain, where the split took effect while a quarter's 13Fs were being filed, is withheld with change_withheld 'split_basis_ambiguous' and the archive's counts in archive_shares, never served as a trade. Dated, refused and labelled like /intel/sec13f; current_quarter changes are against each tracked manager's previous quarter, split-adjusted the same way (managers_without_prior_quarter have none).","query_params":[{"name":"ticker","type":"string"},{"name":"fund","type":"string"},{"name":"min_pct","type":"float","default":0.0,"min":0.0,"max":10.0,"description":"A FRACTION, not a percent, unlike every other *_pct param: 0.5 keeps managers whose share count changed by at least 50% either way, 0.05 keeps 5%. The rows' change_pct is a fraction too (-0.25 = -25%). New and fully closed positions always pass; 0 (default) keeps every change."},{"name":"limit","type":"int","default":50,"min":1,"max":500}],"admin":false,"display_name":"Institutional changes","public_name":"intel_sec13f_changes"},{"name":"tengu_v3_intel_top_shareholders","method":"GET","path":"/api/v3/intel/top_shareholders/{ticker}","group":"v3","description":"Top institutional / fund / insider shareholders for a ticker (13F archive first, alternative-data fallback), as two lists — ownership (shares) and ownership_options (contracts) — because options exposure reads differently from equity holdings. Call this when the user asks 'who owns X?' or wants the largest holders. Archive answers hold share positions only: ownership_options is null (unknown, not empty) and pct_outstanding is null, each with a *_reason. Archive answers carry newest_report_period, vendor_ceiling and is_stale, security_key (read on the share class's CUSIP), missing_known_filers for manager families the archive does not carry that quarter, and holder_current_name where a holder label is a former name; when neither source can answer the route returns 503 upstream_unavailable (not billed), never an empty list.","path_params":["ticker"],"admin":false,"display_name":"Top shareholders","public_name":"intel_top_shareholders"},{"name":"tengu_v3_intel_street_estimates","method":"GET","path":"/api/v3/intel/street_estimates/{ticker}","group":"v3","description":"Street consensus EPS + options-implied expected move per earnings event, with an 8-quarter history (est vs actual vs surprise_pct). Call this for 'what does the Street expect?' or 'how big a move is priced in?'. report_date_basis 'estimation' = projected date, NOT confirmed. next_report_resolved is the ONE next-report date shared with tengu_v3_earnings_next (status confirmed|projected|unknown|not_applicable; confirmed_by company = the company announced it; a symbol neither the security master nor the market-data listing knows is 404 unknown_ticker; inputs.consensus 'unavailable' = the calendar consensus was not ready in time, retry for the settled date). eps_basis is 'unknown' for this feed's actual_eps (see eps_basis_note): its surprise may compare different EPS bases, so beat_rate_pct is null here; for a basis-labelled actual vs estimate and a beat rate use tengu_v3_intel_earnings_history (eps_basis 'adjusted'). A quarter whose actual is a whole split ratio off the street mean (likely a split applied to one figure only) has actual_eps and its surprise null, actual_eps_reason 'split_basis_mismatch'. post_earnings_move_1d is a fraction, post_earnings_move_1d_pct the same move in percent (units lists each field). No fiscal-year or revenue consensus and no analyst count (consensus_note). fiscal_quarter_end is a month end, not the issuer's period end. A ticker that is not a plain symbol ([A-Z][A-Z0-9.-]{0,11} after upper-casing, so not X:BTCUSD or ^VIX) is a 400 invalid_ticker.","path_params":["ticker"],"admin":false,"public_name":"intel_street_estimates"},{"name":"tengu_v3_intel_news_headlines","method":"GET","path":"/api/v3/intel/news_headlines","group":"v3","description":"MARKET-WIDE ONLY — never for one ticker's news (that is tengu_v3_news_summary). Live cross-publisher newswire headlines: headline, publisher, tickers, is_major flag, and the feed's own sentiment label, which is almost always 'neutral' and is not a sentiment read; seconds-fresh, 120s cache. For 'what's happening in the market right now?' scans and cross-ticker sweeps.","query_params":[{"name":"ticker","type":"string","description":"Optional ticker filter"},{"name":"limit","type":"int","default":50,"min":1,"max":100}],"admin":false,"public_name":"intel_news_headlines"},{"name":"tengu_v3_macro_treasury_curve","method":"GET","path":"/api/v3/macro/treasury_curve","group":"v3","description":"US Treasury yield curve from the Treasury's own daily par yield curve, posted the same business day: all 11 tenors 1m-30y, per-tenor 1-day change (bps, from the previous business day's curve), computed 2s10s and 3m10y spreads with inversion flags. Call this when the user asks about rates, curve shape, or inversion. as_of = the curve date; `label` names the source and date to quote (\"Live\" only for today's curve); is_stale and freshness.business_days_behind grade it against the latest official curve. When no current copy of the Treasury's curve is held, a market-data copy posted a business day later is served and labelled; a null tenor carries null_reason.","admin":false,"public_name":"macro_treasury_curve"},{"name":"tengu_v3_intel_exec_compensation","method":"GET","path":"/api/v3/intel/exec_compensation/{ticker}","group":"v3","description":"Annual executive compensation history for a ticker (alternative-data): CEO + named officers, one row per executive and fiscal year, with name, role, year, salary, stock_and_option_awards (stock AND option awards together; stock_option_awards is the same figure under its old name), total_compensation, all in USD. bonus is withheld (null, bonus_reason): the feed mixes incentive-plan pay into it. Call this when the user asks 'how much is the CEO paid?' or wants pay-vs-performance context.","path_params":["ticker"],"query_params":[{"name":"limit","type":"int","default":25,"min":1,"max":200}],"admin":false,"display_name":"Executive pay","public_name":"intel_exec_compensation"},{"name":"tengu_v3_intel_etf_holdings","method":"GET","path":"/api/v3/intel/etf_holdings","group":"v3","description":"ETF composition or inverse-lookup. Pass ?etf=SPY for the holdings in the fund's newest file, largest weight first (total_holdings and weight_sum_pct cover every line of the copy, whatever limit is; each weight is the fund's own, over its net assets, not normalised, so they can add to more than 100: weight_sum_basis; non_security_lines are its cash, collateral, cash fund and futures lines, securities_weight_pct the rest), OR ?ticker=NVDA for which of the covered ETFs hold the stock (with weight): coverage.etfs_searched lists the funds searched (the broad-market funds and the SPDR sector funds), and an ETF outside that list may hold it too. snapshot_date and as_of are the day the file was captured, not the day its weights were priced (usually the previous trading day's close; weights_priced_as_of is null). At least one is required; when both are passed, etf takes precedence.","query_params":[{"name":"etf","type":"string","description":"ETF symbol — full holdings"},{"name":"ticker","type":"string","description":"Stock symbol — which ETFs hold it"},{"name":"limit","type":"int","default":50,"min":1,"max":1000}],"param_constraints":[{"at_least_one_of":["etf","ticker"]}],"admin":false,"display_name":"ETF holdings","public_name":"intel_etf_holdings"},{"name":"tengu_v3_intel_politicians","method":"GET","path":"/api/v3/intel/politicians","group":"v3","description":"Full US Congress roster (House + Senate, alternative-data) with disclosed trade counts per member. trade_count is the source's running count with no stated window or as-of date (trade_count_note), not recent activity; party_code matches tengu_v3_intel_congress. Call it to resolve a politician name to a BioGuideID before pulling their trades, or for 'most-active disclosed traders in Congress' lists. Heavy full-roster pull.","query_params":[{"name":"limit","type":"int","default":100,"min":1,"max":1000}],"admin":false,"display_name":"Politician trades","capability_tags":["heavy"],"public_name":"intel_politicians"},{"name":"tengu_v3_intel_corporate_donors","method":"GET","path":"/api/v3/intel/corporate_donors/{ticker}","group":"v3","description":"Corporate-PAC donations linked to the ticker's parent company (alternative-data): candidate, committee, amount, transaction_date, cycle — a campaign-finance influence signal, newest first (newest_date). An empty list is the source's answer for a symbol the security master carries; an unknown symbol is a 404 unknown_ticker. Call this when the user asks who a company donates to or about its political exposure.","path_params":["ticker"],"query_params":[{"name":"limit","type":"int","default":50,"min":1,"max":500}],"admin":false,"display_name":"Corporate donors","public_name":"intel_corporate_donors"},{"name":"tengu_v3_intel_gov_contracts_live","method":"GET","path":"/api/v3/intel/gov_contracts_live","group":"v3","description":"Quarterly federal-contract award totals across tickers (alternative-data): one total per ticker and US federal fiscal quarter (fiscal_basis, period_start/period_end; Q1 is October-December), newest quarter first and largest total first within it. Totals only, with no agency or award detail. Call this for 'which companies win government money?' screens; tengu_v3_intel_gov_contracts gives one ticker's quarterly history.","query_params":[{"name":"ticker","type":"string","description":"Optional filter"},{"name":"limit","type":"int","default":50,"min":1,"max":500}],"admin":false,"display_name":"Government contracts (live)","public_name":"intel_gov_contracts_live"},{"name":"tengu_v3_intel_news_pro","method":"GET","path":"/api/v3/intel/news_pro","group":"v3","description":"Newswire stories, live: cross-ticker, by ticker (comma-separated, up to 20) or by channel, newest first, with history back to 2018 via date_from / date_to (UTC days, inclusive, at most 366 days). Each item: id, title, teaser, url, ticker, tickers, coins (crypto assets named), channels and tags (lower case), author, published (UTC; created is the same instant) and updated; body=true adds the full HTML body. Channel names are the feed's, lower case, e.g. 'movers', 'press releases', 'cryptocurrency', 'earnings', 'guidance', 'analyst ratings', 'price target', 'markets', 'top stories', 'economics', 'federal reserve'; \"Why It's Moving\" selects the move explainers. as_of is the newest item's publication time. An empty list is a real empty answer (result empty_but_healthy); a feed that did not answer is a 503 refusal, never an empty list. Call it for themed or full-text news beyond headlines.","query_params":[{"name":"tickers","type":"string","description":"Comma-separated symbols, e.g. 'AAPL,MSFT'"},{"name":"channels","type":"string","description":"Comma-separated channel names, lower case (e.g. 'movers', 'press releases'); \"Why It's Moving\" selects the move explainers"},{"name":"limit","type":"int","default":25,"min":1,"max":100},{"name":"body","type":"boolean","default":false,"description":"Include full HTML body (slower, larger)"},{"name":"date_from","type":"string","description":"First UTC day, YYYY-MM-DD (inclusive); history from 2018-01-01"},{"name":"date_to","type":"string","description":"Last UTC day, YYYY-MM-DD (inclusive); at most 366 days after date_from"}],"admin":false,"public_name":"intel_news_pro"},{"name":"tengu_v3_intel_news_why_moving","method":"GET","path":"/api/v3/intel/news_why_moving","group":"v3","description":"'Why It's Moving' explainers, live: short stories on why a stock or coin is making a notable move, newest first, each with catalyst_type (earnings, guidance, analyst, ma, regulatory, capital, contract, personnel, macro or other: a keyword reading of the headline, not a model). Filter by tickers (comma-separated); date_from / date_to (UTC days, inclusive) read past windows back to 2018. Items carry published (UTC), tickers, channels, tags and url; body=true adds the full HTML. Explainers are written on US trading days, so the newest can be a day or more old over a weekend: quote each with its time. Call it first for 'why is X moving today?'.","query_params":[{"name":"tickers","type":"string","description":"Comma-separated symbols (optional — omit for cross-ticker feed)"},{"name":"limit","type":"int","default":25,"min":1,"max":100},{"name":"body","type":"boolean","default":false},{"name":"date_from","type":"string","description":"First UTC day, YYYY-MM-DD (inclusive); history from 2018-01-01"},{"name":"date_to","type":"string","description":"Last UTC day, YYYY-MM-DD (inclusive); at most 366 days after date_from"}],"admin":false,"display_name":"Why it's moving","public_name":"intel_news_why_moving"},{"name":"tengu_v3_intel_news_press_releases","method":"GET","path":"/api/v3/intel/news_press_releases","group":"v3","description":"Company press releases carried on the newswire, live, newest first: title, teaser, url, tickers, published (UTC); body=true adds the full text. Coverage is SPARSE: about fifty releases from March 2024 to September 2026, so the newest can be weeks old (the staleness block grades it against a 14-day cadence) and an empty answer does not show that a company issued none. Filter by tickers; date_from / date_to (UTC days, inclusive) read past windows. Call it for original company announcements carried on the wire.","query_params":[{"name":"tickers","type":"string"},{"name":"limit","type":"int","default":25,"min":1,"max":100},{"name":"body","type":"boolean","default":false},{"name":"date_from","type":"string","description":"First UTC day, YYYY-MM-DD (inclusive); history from 2018-01-01"},{"name":"date_to","type":"string","description":"Last UTC day, YYYY-MM-DD (inclusive); at most 366 days after date_from"}],"admin":false,"display_name":"Press releases","public_name":"intel_news_press_releases"},{"name":"tengu_v3_intel_news_crypto","method":"GET","path":"/api/v3/intel/news_crypto","group":"v3","description":"The newswire's cryptocurrency channel, live, newest first: title, teaser, url, published (UTC), channels, tags, tickers and coins; body=true adds the full HTML. tickers takes coins (BTC, ETH, SOL ...) or coin-stock proxies (COIN, MSTR): a major coin's symbol is read as the coin (flagged ambiguous when it is also a US stock ticker: SOL, LINK, TRX ...); a symbol shared by a smaller coin and a listed stock (DASH, COMP, LIT ...) is read as the STOCK and flagged ambiguous; send X:<COIN>USD for that coin. tickers_read_as says how each was read. In items a coin appears in tickers as X:<COIN>USD and in coins as <COIN>. date_from / date_to (UTC days, inclusive) read past windows back to 2018. Call it for crypto news; an empty list is a real empty answer, a feed that did not answer is a 503 refusal.","query_params":[{"name":"tickers","type":"string","description":"Crypto tickers (BTC, ETH) or coin-stock proxies (COIN, MSTR)"},{"name":"limit","type":"int","default":25,"min":1,"max":100},{"name":"body","type":"boolean","default":false},{"name":"date_from","type":"string","description":"First UTC day, YYYY-MM-DD (inclusive); history from 2018-01-01"},{"name":"date_to","type":"string","description":"Last UTC day, YYYY-MM-DD (inclusive); at most 366 days after date_from"},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional: this tool serves crypto only, so crypto is the one value."}],"admin":false,"display_name":"Crypto newswire","public_name":"intel_news_crypto"},{"name":"tengu_v3_intel_news_movers","method":"GET","path":"/api/v3/intel/news_movers","group":"v3","description":"The newswire's movers channel, live, newest first: stories on the biggest gainers, losers, halts and breakouts, with title, teaser, url, tickers and published (UTC); body=true adds the full HTML. Filter by tickers; date_from / date_to (UTC days, inclusive) read past windows back to 2018. Quote each story with its time: a story from an earlier session is not today's mover. Call it for 'what moved today' questions and end-of-day recaps.","query_params":[{"name":"tickers","type":"string"},{"name":"limit","type":"int","default":25,"min":1,"max":100},{"name":"body","type":"boolean","default":false},{"name":"date_from","type":"string","description":"First UTC day, YYYY-MM-DD (inclusive); history from 2018-01-01"},{"name":"date_to","type":"string","description":"Last UTC day, YYYY-MM-DD (inclusive); at most 366 days after date_from"}],"admin":false,"display_name":"Today's movers","public_name":"intel_news_movers"},{"name":"tengu_v3_intel_earnings_history","method":"GET","path":"/api/v3/intel/earnings_history/{ticker}","group":"v3","description":"Last N quarters of earnings for a ticker — report date, EPS estimate vs actual, surprise %, and the earnings-reaction price move %. Used by the verdict prompt to anchor 'stock typically moves ±X% on earnings' claims in real numbers. EPS is the estimates vendor's adjusted EPS (eps_basis 'adjusted', the basis the consensus estimate is struck on): the issuer's own non-GAAP EPS where it publishes one, otherwise the vendor's own adjustment (eps_basis_note). report_date is the announcement date (it used to be the calendar-quarter end; null when unknown); calendar_quarter_end is the estimates feed's period label and fiscal_quarter_end identifies the quarter. day_move_pct is the open-to-close move of the session that traded on the release: the NEXT session for an after-close report (it used to be the report date's own session, before the news). day_move_date names that session; day_move_basis is reaction_session | release_time_unknown (first session on or after report_date) | reaction_session_pending (not closed yet; the move is null). reaction_move_pct is the last close before the release to the reaction close (null unless the release time is known), summarized by avg/max_abs_reaction_move_pct beside avg/max_abs_day_move_pct. warning report_dates_unavailable = the date source failed. eps_estimate is the estimates feed's current consensus for the quarter, undated (eps_estimate_as_of null), not a pre-report snapshot; street_mean_eps is the options-flow feed's for the same quarter. surprise_outcome is beat|miss|in_line when the actual is on the same side of both, 'uncertain' when they straddle it (surprise_outcome_reason); beat_rate_pct counts beats among quarters_scored and leaves quarters_uncertain out, and quarters_excluded_split_basis too: an actual 4 or more whole times its estimate is withheld (split_basis_mismatch), one 2 or 3 times is served flagged split_check with surprise_status basis_unconfirmed. quarters_returned can be fewer than lookback_quarters (lookback_note): the feed answers only its most recent quarters, 4 today. Composite (estimates feed + options-flow report dates + daily bars). 6h cache.","path_params":["ticker"],"query_params":[{"name":"lookback_quarters","type":"int","default":4,"min":1,"max":12,"description":"Number of past earnings events to return. The estimates feed answers only its most recent 4 quarters today; quarters_returned says how many came back."}],"admin":false,"display_name":"Earnings history","public_name":"intel_earnings_history"},{"name":"tengu_v3_earnings_next","method":"GET","path":"/api/v3/earnings/next/{ticker}","group":"v3","description":"Use when: the user asks for a specific ticker's next earnings date, when a company reports, the earnings calendar entry for a name, or anything of the form \"when is X's next earnings?\". This is the CANONICAL multi-source consensus tool — fans out to the market-data listing, the estimates calendar, the options-flow calendar, the news feed and web search; reconciles via primacy-weighted majority; returns a single canonical answer with per-source breakdown and deduplicated citations. ``confirmed`` / next_earnings_date mean a source says the COMPANY announced the date; a calendar row or a web date is a projection, served in ``_meta.domain.next_earnings_date_projection_only`` (projected_by lists the sources) with ``_meta.confidence`` `low`. `high` = ≥2 confirming sources or the exchange listing alone, `medium` = one other confirming source. Ties go to the documented source priority, web search last. Top-level ``summary`` field for FE rendering. A fund, warrant or preferred line answers ``status: not_applicable`` with ``not_applicable_reason``; a symbol neither the security master nor the market-data listing knows is 404 unknown_ticker; symbol_in_security_master is false (the master lacks it, e.g. a new listing) or null (not checked) with a symbol_check_note. ``next_report_resolved`` is the ONE next-report date shared with tengu_v3_intel_street_estimates (status confirmed|projected|unknown|not_applicable; confirmed_by company = the company announced it; source; alternatives; inputs 'not_consulted' for a non-symbol ticker or a not-applicable one). Read the date from next_report_resolved.date. most_recent_reported_date comes from the options-flow calendar whenever it has a report: its last with an actual EPS (most_recent_reported_status calendar_with_actuals), or a newer company-dated report whose results are not in yet (reported_actuals_pending). A date found only in web text is unverified, or unverified_newer_than_calendar when it is newer than the calendar's report and could be the next quarter's (only when the calendar row names its fiscal quarter end). The dates not taken are in most_recent_reported_alternatives, with a calendar date that passed without results (projected_date_passed_no_actuals, company_date_passed_no_results). revenue_estimate is a vendor's consensus line (revenue_estimate_basis), not comparable with filed total revenue. 1h cache.","path_params":["ticker"],"query_params":[],"admin":false,"display_name":"Next earnings (consensus)","capability_tags":["consensus_envelope_v1","heavy"],"response_schema":{"$defs":{"Citation":{"additionalProperties":true,"description":"One source cited for the answer: the publisher, the page and,\nwhen available, a stable URL of the publisher's icon.","properties":{"source":{"description":"Publisher display name (e.g. 'NVIDIA Investor Relations').","title":"Source","type":"string"},"url":{"description":"Canonical URL of the cited page.","title":"Url","type":"string"},"favicon":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Publisher icon URL.","title":"Favicon"}},"required":["source","url"],"title":"Citation","type":"object"},"ConsensusEnvelope":{"description":"The `_meta` block every consensus tool must emit.\n\nRequired fields are the **universal data-correctness contract**.\nThe `domain` slot is an open dict for tool-specific extension —\ne.g. earnings_next puts `next_earnings_date_projection_only` in\n`domain`, dividend_next would put `projected_amount_per_share`,\netc. The required fields stay stable; domain extensions evolve\nper tool.","properties":{"schema_version":{"default":"1.0","description":"Contract version. Bumped on breaking changes.","title":"Schema Version","type":"string"},"confidence":{"description":"Honest assessment of how trustworthy the canonical answer is. 'high' requires multi-source agreement OR single-source confirmation from a Tier-1 primary.","enum":["high","medium","low","unknown"],"title":"Confidence","type":"string"},"coverage":{"description":"Whether the canonical answer is grounded in confirmed data ('confirmed'), only projections ('not_confirmed'), or nothing at all ('unknown').","enum":["confirmed","not_confirmed","unknown"],"title":"Coverage","type":"string"},"is_projected":{"description":"True if the canonical answer is a projection (vendor estimate / model output / pattern-derived) rather than a vendor-confirmed fact.","title":"Is Projected","type":"boolean"},"sources_attempted":{"description":"Every source the tool tried, in the order they were queried (typically the primacy order).","items":{"type":"string"},"title":"Sources Attempted","type":"array"},"sources_confirming":{"description":"Sources that returned confirmed data.","items":{"type":"string"},"title":"Sources Confirming","type":"array"},"sources_silent":{"description":"Sources that returned no data (vendor gaps).","items":{"type":"string"},"title":"Sources Silent","type":"array"},"primary_source":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The single source the canonical answer is attributed to. None when coverage is 'unknown'.","title":"Primary Source"},"sources_agreed":{"description":"Count of sources confirming the SAME canonical value.","minimum":0,"title":"Sources Agreed","type":"integer"},"sources_total":{"description":"Total sources queried (= len(sources_attempted)).","minimum":0,"title":"Sources Total","type":"integer"},"data_freshness_utc":{"description":"ISO-8601 UTC timestamp of when this response was composed. Z-suffix required.","title":"Data Freshness Utc","type":"string"},"domain":{"additionalProperties":true,"description":"Open extension slot for tool-specific meta fields. Use this for projection details, calendar-specific metadata, vendor-specific quirks, etc. Required fields above stay stable; domain extensions evolve per tool.","title":"Domain","type":"object"}},"required":["confidence","coverage","is_projected","sources_attempted","sources_confirming","sources_silent","primary_source","sources_agreed","sources_total","data_freshness_utc"],"title":"ConsensusEnvelope","type":"object"},"MostRecentReportedAlternative":{"description":"A past report date the answer did not take, and why it is weaker.","properties":{"date":{"title":"Date","type":"string"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Source"},"status":{"anyOf":[{"enum":["calendar_with_actuals","reported_actuals_pending","unverified_newer_than_calendar","unverified","company_date_passed_no_results","projected_date_passed_no_actuals"],"type":"string"},{"type":"null"}],"default":null,"title":"Status"}},"required":["date"],"title":"MostRecentReportedAlternative","type":"object"},"NextReportAlternative":{"description":"A candidate date the resolver did not choose, and where it came\nfrom.","properties":{"date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date"},"status":{"enum":["confirmed","projected"],"title":"Status","type":"string"},"source":{"title":"Source","type":"string"}},"required":["date","status","source"],"title":"NextReportAlternative","type":"object"},"NextReportInputs":{"description":"Which sources the resolved date was resolved from.","properties":{"options_flow":{"enum":["consulted","unavailable","not_consulted"],"title":"Options Flow","type":"string"},"consensus":{"description":"'not_needed': the issuer confirmed the date, so the calendar consensus could not change the answer; 'unavailable': it was not ready in time, and the date may change on a later call; 'not_consulted' (both inputs): the ticker is not a symbol, so no source was asked.","enum":["consulted","not_needed","unavailable","not_consulted"],"title":"Consensus","type":"string"}},"required":["options_flow","consensus"],"title":"NextReportInputs","type":"object"},"NextReportResolved":{"description":"The ONE next-report date ``/earnings/next`` and\n``/intel/street_estimates`` both serve (2026-09-24: NVDA was\n2026-11-17 on one and 2026-11-18 on the other). The rule lives in\n``_earnings_contract.resolve_next_report``.","properties":{"date":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"ISO YYYY-MM-DD, or null.","title":"Date"},"status":{"enum":["confirmed","projected","unknown","not_applicable"],"title":"Status","type":"string"},"source":{"title":"Source","type":"string"},"confirmed_by":{"anyOf":[{"enum":["company","vendor_consensus"],"type":"string"},{"type":"null"}],"default":null,"description":"'company': a source says the company announced it. 'vendor_consensus' (calendars and web search agree) is no longer served: since 2026-09-29 that is a projection.","title":"Confirmed By"},"time_of_day":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Time Of Day"},"sources_agreed":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Sources Agreed"},"alternatives":{"items":{"$ref":"#/$defs/NextReportAlternative"},"title":"Alternatives","type":"array"},"resolver":{"title":"Resolver","type":"string"},"inputs":{"$ref":"#/$defs/NextReportInputs"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Why there is no date, when status is 'not_applicable' (the security has no earnings of its own, e.g. a fund).","title":"Reason"}},"required":["date","status","source","alternatives","resolver","inputs"],"title":"NextReportResolved","type":"object"},"PerSourceResult":{"additionalProperties":true,"description":"What one source returned. The canonical answer is reconciled\nfrom these rows, one per source asked.","properties":{"source":{"title":"Source","type":"string"},"date":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"ISO YYYY-MM-DD or None","title":"Date"},"confirmed":{"default":false,"title":"Confirmed","type":"boolean"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Vendor-specific failure mode tag ('vendor_returned_no_upcoming_event', etc.).","title":"Reason"},"projection_date":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Projection Date"},"fiscal_period":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Fiscal Period"},"eps_estimate":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Eps Estimate"},"revenue_estimate":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Revenue Estimate"}},"required":["source"],"title":"PerSourceResult","type":"object"},"VendorCoverageAlert":{"description":"Present when web search confirmed the event date and one or more\ncalendar sources had not published it yet. Informational: it names\nthe sources that were behind, not a problem with the answer.","properties":{"severity":{"description":"'high' when three or more sources had not published the web-confirmed date; 'moderate' otherwise.","enum":["moderate","high"],"title":"Severity","type":"string"},"vendors_silent_on_known_event":{"items":{"type":"string"},"title":"Vendors Silent On Known Event","type":"array"},"web_confirmed_date":{"title":"Web Confirmed Date","type":"string"},"operator_action":{"description":"Deprecated: an informational sentence, to be removed. Read vendors_silent_on_known_event instead.","title":"Operator Action","type":"string"}},"required":["severity","vendors_silent_on_known_event","web_confirmed_date","operator_action"],"title":"VendorCoverageAlert","type":"object"}},"description":"The full response of ``GET /api/v3/earnings/next/{ticker}``: the\nconsensus answer inside the standard v3 envelope (``ok`` and\n``timestamp`` at the top level). `_meta` is the ConsensusEnvelope\nevery consensus-class tool emits.","properties":{"ok":{"title":"Ok","type":"boolean"},"timestamp":{"title":"Timestamp","type":"string"},"ticker":{"title":"Ticker","type":"string"},"status":{"anyOf":[{"const":"not_applicable","type":"string"},{"type":"null"}],"default":null,"title":"Status"},"not_applicable_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Not Applicable Reason"},"symbol_in_security_master":{"anyOf":[{"type":"boolean"},{"type":"null"}],"default":null,"title":"Symbol In Security Master"},"symbol_check_note":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Symbol Check Note"},"next_earnings_date":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"ISO YYYY-MM-DD. NULL unless a source says the company announced the date — projections never appear here.","title":"Next Earnings Date"},"time_of_day":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"BMO | AMC | DMT | None","title":"Time Of Day"},"confirmed":{"title":"Confirmed","type":"boolean"},"fiscal_period":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Fiscal Period"},"eps_estimate":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Eps Estimate"},"revenue_estimate":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Revenue Estimate"},"revenue_estimate_basis":{"anyOf":[{"const":"vendor_consensus_line","type":"string"},{"type":"null"}],"default":null,"title":"Revenue Estimate Basis"},"revenue_estimate_note":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Revenue Estimate Note"},"days_until":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Days Until"},"primary_source":{"description":"Source that the canonical answer is attributed to. 'none' when nothing was found anywhere.","title":"Primary Source","type":"string"},"sources_agreed":{"minimum":0,"title":"Sources Agreed","type":"integer"},"sources_total":{"minimum":0,"title":"Sources Total","type":"integer"},"most_recent_reported_date":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"ISO YYYY-MM-DD of the most recent earnings that was already reported (looking back from today). Populated even when next_earnings_date is None — honest 'past' context for the chat surface.","title":"Most Recent Reported Date"},"most_recent_reported_source":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Source code (for example web_search or estimates_feed) that surfaced the most recent past date.","title":"Most Recent Reported Source"},"most_recent_reported_days_ago":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"description":"Whole days between today and ``most_recent_reported_date`` (positive ⇒ past).","title":"Most Recent Reported Days Ago"},"most_recent_reported_status":{"anyOf":[{"enum":["calendar_with_actuals","reported_actuals_pending","unverified_newer_than_calendar","unverified"],"type":"string"},{"type":"null"}],"default":null,"title":"Most Recent Reported Status"},"most_recent_reported_alternatives":{"anyOf":[{"items":{"$ref":"#/$defs/MostRecentReportedAlternative"},"type":"array"},{"type":"null"}],"default":null,"title":"Most Recent Reported Alternatives"},"next_report_resolved":{"anyOf":[{"$ref":"#/$defs/NextReportResolved"},{"type":"null"}],"default":null},"summary":{"description":"A one-line summary of the answer, present on every response including the no-data path.","minLength":1,"title":"Summary","type":"string"},"citations":{"items":{"$ref":"#/$defs/Citation"},"title":"Citations","type":"array"},"per_source":{"items":{"$ref":"#/$defs/PerSourceResult"},"title":"Per Source","type":"array"},"vendor_coverage_alert":{"anyOf":[{"$ref":"#/$defs/VendorCoverageAlert"},{"type":"null"}],"default":null},"data_freshness":{"description":"ISO-8601 UTC, Z-suffixed.","title":"Data Freshness","type":"string"},"_meta":{"$ref":"#/$defs/ConsensusEnvelope","description":"The universal `_meta` envelope (ConsensusEnvelope). Every consensus-class tool emits this same shape."},"warning":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Present only on a degraded response: an internal error was caught, so this is not a successful answer.","title":"Warning"}},"required":["ok","timestamp","ticker","next_earnings_date","confirmed","primary_source","sources_agreed","sources_total","summary","citations","per_source","data_freshness","_meta"],"title":"EarningsNextResponse","type":"object"},"public_name":"earnings_next"},{"name":"tengu_v3_earnings_next_stream","method":"GET","path":"/api/v3/earnings/next/{ticker}/stream","group":"v3","description":"STREAMING variant of ``tengu_v3_earnings_next`` — same consensus contract, delivered as Server-Sent Events (text/event-stream). Emits two events: ``partial`` when the paid sources settle the answer (~500ms first paint: a company-confirmed date, or two agreeing sources), then ``result`` at once, the same answer the JSON route serves; when they do not, only ``result``, after web search (~2-3s). Both carry next_report_resolved, as the JSON route does. Use when a consumer can render incrementally and wants the fastest possible first paint — chat surfaces and live tickers. Synchronous consumers should keep using ``tengu_v3_earnings_next`` (cost-aware: skips the web_search call entirely when paid agrees).","path_params":["ticker"],"query_params":[],"admin":false,"capability_tags":["chat_excluded","sse"],"public_name":"earnings_next_stream"},{"name":"tengu_v3_intel_macro_snapshot","method":"GET","path":"/api/v3/intel/macro_snapshot","group":"v3","description":"NOW WITH a `credit` block: CDX IG/HY on-the-run 5Y composite spreads + 1-session delta (T-2 by source, cadence-aware staleness; full series at /api/v3/credit/indices). Cross-asset macro composite returning REAL underlying values, all real-time where the data source permits. Fields: `vix` (real-time spot), `ten_year_yield_pct` (10-year Treasury par yield, %, from the Treasury's same-day curve; its 1-day move is `change_1d_bps`, in basis points; the indicator carries as_of, source and business days behind the latest official curve), `usd_index_narrow_dxy` (computed from live spot quotes of the six pairs via the standard geometric weighted formula — the institutional standard ~99), `usd_index_trade_weighted_broad` (FRED DTWEXBGS — Fed's broader policy measure ~118), `wti_oil_usd_bbl` (front-month WTI futures, $/bbl — the contract intel_commodities serves, named in `contract`; the dated physical spot is in `physical_spot`), `gold_usd_oz` (live spot quote, $/oz, stamped with the quote time), `sp500` (real-time index; SPY×10 emergency fallback), `nasdaq100` (real-time index; QQQ×41 emergency fallback), `djia` (real-time index; null when unavailable — no ETF proxy emitted), `russell2000` (real-time index; IWM×10 emergency fallback). Every numeric field is gated by a plausibility guard — out-of-band values are nulled with an `error.implausible_value` field rather than served, so a wrong number is never served. Includes `vol_regime` (low_vol/normal/elevated/stress per VIX bucket), `data_freshness` timestamp, and a `sources` block with the series reference for each indicator. `nowcasts` fields carry `reference_period` (the quarter/week/day described) apart from `as_of` (the print). The `credit` delta compares one CDX series and version only; across a roll it is null with `delta_reason` 'index_roll' and a `roll` block. `releases`: latest official CPI, PCE, unemployment, payrolls, GDP growth and fed funds, each with reference_period, released date and 1m/12m changes. 60s cache.","query_params":[{"name":"freshness","type":"string","default":"off","enum":["off","live","strict"],"description":"Freshness policy. 'off' serves with an age footnote; 'live'/'strict' return 503 data_stale rather than serve stale data"}],"admin":false,"display_name":"Cross-asset snapshot","public_name":"intel_macro_snapshot"},{"name":"tengu_v3_intel_ml_prediction","method":"GET","path":"/api/v3/intel/ml_prediction/{ticker}","group":"v3","description":"Stored equity model SCORE, available voter evidence, and nullable interval bounds. predicted_return_pct IS blended_score*100: a scored ordering, not a forecast. Size and compare on rank/percentile/decile (decile_convention=10_is_best), never on the magnitude. Inspect source date and prediction_evidence_available. Adaptive intervals may be asymmetric: half_width is a maximum residual offset, not necessarily half the span. Numeric compatibility does not establish calibration or measured coverage; stated and recent coverage remain unavailable without matching artifacts. Research only; capital_authorized is false. Pass asset_class=equity or crypto explicitly for ambiguous ticker symbols.","path_params":["ticker"],"query_params":[{"name":"asset_class","type":"string","default":"equity","enum":["equity","crypto"],"description":"Asset namespace; crypto fails closed with 404: no crypto model serves this route"}],"admin":false,"display_name":"Quant signal","public_name":"intel_ml_prediction"},{"name":"tengu_v3_intel_voter_attribution","method":"GET","path":"/api/v3/intel/voter_attribution/{ticker}","group":"v3","description":"Causal attribution for a voter's score on a ticker. Instrumented voters: `insider_flow` (EDGAR Form-4 + insider feed, deduped by name/date/value; CEO/CFO 2x, officer 1.5x, director 1.2x weighting; contribution amounts + reconstructed score); `options_flow` (options-flow alerts with direction inferred from option_type+side: CALL@ASK=+1, PUT@ASK=-1, CALL@BID=-1, PUT@BID=+1; weighted by premium/median); `fundamental` (metadata mode — surfaces which 4 ratios the voter consumes + how to interpret). Transforms scores into EVIDENCE rather than a number. Remaining voters (sentiment, analyst_revisions, regime_hmm, technical, ml_ensemble) pending instrumentation. Optional ?voter=insider_flow|options_flow|fundamental, ?days_back=30. 15min cache.","path_params":["ticker"],"query_params":["voter",{"name":"days_back","type":"int","default":30,"min":1,"max":90}],"admin":false,"display_name":"Signal drivers","public_name":"intel_voter_attribution"},{"name":"tengu_v3_intel_voter_ic_drift","method":"GET","path":"/api/v3/intel/voter_ic_drift","group":"v3","description":"UNAVAILABLE: the voter IC-drift table is empty (not produced yet), so the answer has no voter rows. Per-voter information-coefficient drift vs baseline for all 19 voters, recomputed daily: live_ic vs baseline_ic, ic_ratio (sign-flip flagged at <0), drift_status (green/yellow/red), sorted by absolute drift severity. Call it before leaning on a verdict — reduce confidence in any voter with red drift_status. 60min cache.","path_params":[],"query_params":[],"admin":false,"display_name":"Voter IC drift (raw)","public_name":"intel_voter_ic_drift"},{"name":"tengu_v3_intel_voter_coverage","method":"GET","path":"/api/v3/intel/voter_coverage/{ticker}","group":"v3","description":"Per-ticker accounting for every voter in the 19-voter ensemble. For each voter returns the current score, the weight it was blended with (weight: 0 for a voter the voter policy disables) beside its nominal_weight, status (firing | disabled_at_blend | unverified | silent_data | shadow | no_signal), and a human-readable `why` explaining each silent voter's upstream data source so an operator can chase the gap. The `coverage_summary` block reports `weight_firing` (effective ensemble weight in use) vs `weight_silent_live` (paid-for but silent). When the voter policy could not be applied, scored voters are `unverified` and the weight figures and effective_coverage are null with effective_coverage_reason. Use this when a model_prediction shows low voter_coverage — it tells you exactly which data pipelines to wake up. 5min cache.","path_params":["ticker"],"query_params":[],"admin":false,"display_name":"Signal coverage","public_name":"intel_voter_coverage"},{"name":"tengu_v3_intel_ml_drivers","method":"GET","path":"/api/v3/intel/ml_drivers/{ticker}","group":"v3","description":"UNAVAILABLE: no SHAP drivers can be served. The drivers file does not record which model bundle produced it, so it cannot be tied to the model serving now; every call answers 503 upstream_dead_drivers_unbound until a bound file is published. Top-N SHAP feature attributions for the ML ensemble score on a ticker: drivers[] ranked by |SHAP| with feature (e.g. beta_cma, vol_21d), signed shap_value, direction (bullish/bearish/neutral). PRIMARY tool for 'why is the model bullish/bearish on X?'. Nightly run; default top=5, max 20; available:false outside the ML universe. 5min cache. Served only when the drivers name the active model bundle; otherwise a 503 refusal, not billed (error_code upstream_dead_drivers_unbound, `binding.status` unbound | foreign_bundle | mixed_bundles | active_bundle_unknown) — say the drivers are unavailable, never that the ticker is outside the universe, never substitute. Every 200, including available:false, carries as_of, model_bundle_sha256 and `stale` (over 3 days): available:false is a statement about that run's universe.","path_params":["ticker"],"query_params":[{"name":"top","type":"int","default":5}],"admin":false,"display_name":"What's driving it","public_name":"intel_ml_drivers"},{"name":"tengu_v3_intel_model_calibration","method":"GET","path":"/api/v3/intel/model_calibration","group":"v3","description":"Calibration migration status. Recent realised coverage is unavailable because legacy one-day outcomes do not match the current prediction bundle and horizon. No 90% coverage or current red/amber/green performance claim is provided.","query_params":[],"admin":false,"display_name":"Model calibration","public_name":"intel_model_calibration"},{"name":"tengu_v3_intel_cftc_cot","method":"GET","path":"/api/v3/intel/cftc_cot","group":"v3","description":"CFTC Commitments-of-Traders positioning for COMMODITY futures (the Disaggregated report: energy, metals, grains, livestock, softs) by cohort: producers/merchants, money managers, other reportables, non-reportables (no swap-dealer cohort, so cohort nets do not sum to zero). Positions as of Tuesday, polled Fridays at 18:00 ET after the CFTC publishes. Without filter: top-10 money-manager longs and shorts on the latest report. `?contract=` resolves to ONE contract: an alias (GOLD, WTI, NATGAS, SILVER, COPPER, CORN, SOYBEANS, SUGAR, ...), an exact CFTC contract name, or a name part that matches one contract; returns its own last 5 weekly reports with cohort nets, % of OI, and the money-manager change against its report 4 weeks earlier. A name matching several contracts (e.g. WHEAT) is a 409 listing them. Financial futures (E-mini S&P, Treasuries, currencies, VIX, bitcoin) are in the Traders in Financial Futures report, which is not covered: 404 contract_not_in_report. Extreme money-manager longs at the top of a rally historically mark exhaustion. 4h cache (weekly data).","query_params":["contract"],"admin":false,"display_name":"Futures positioning","public_name":"intel_cftc_cot"},{"name":"tengu_v3_volatility_vix_indices","method":"GET","path":"/api/v3/volatility/vix_indices","group":"v3","description":"VOLATILITY INDEX HISTORY: daily open, high, low and close of VIX (S&P 500 30-day implied volatility), VXO (S&P 100, the original method), VXN (Nasdaq-100) and VXD (Dow Jones Industrial Average); VIX from 1990-01-02, VXO from 1986, each series' coverage states its own range. Values are index points = annualised implied volatility in percent (20.0 = 20% a year over the next 30 days). An end-of-day archive delivered in monthly batches, not a live quote: freshness.data_through is its newest session and freshness.stale turns true past 49 days. start/end (YYYY-MM-DD) bound the window, default the year to the newest session; limit caps sessions per index, newest kept (truncated says so). Each series states its coverage, and series_ended when the source stopped publishing it. Some 1990-2003 VIX sessions have no intraday range (range_withheld says why). Use for volatility regimes, stress history and backtests. 6h cache.","query_params":[{"name":"index","type":"string","default":"vix","enum":["vix","vxo","vxn","vxd","all"],"description":"Which index; all returns the four"},{"name":"start","type":"string","description":"First session, YYYY-MM-DD"},{"name":"end","type":"string","description":"Last session, YYYY-MM-DD; default the newest"},{"name":"limit","type":"int","default":260,"min":1,"max":2600,"description":"Most sessions per index; the newest are kept"}],"admin":false,"display_name":"Volatility index history","public_name":"volatility_vix_indices"},{"name":"tengu_v3_volatility_vx_curve","method":"GET","path":"/api/v3/volatility/vx_curve","group":"v3","description":"VIX FUTURES CURVE: the monthly VIX futures' daily settlements for one session (contract_month, expiration, days_to_expiration, settlement in VIX index points; 1 point = USD 1,000 per contract) and its term structure: front, second and back month, second_over_front_pct (percent) and state = contango (second above front, the usual state) or backwardation (front above second, typical of stress). history gives the last N sessions' front, second, back and state. Default the newest session (one per trading day, written that evening); date=YYYY-MM-DD for an earlier one (404 with the nearest prior session if none). History from August 2026. On a contract's expiry day its final settlement is served apart (final_settlement) and the front is the next contract. Rows captured before 2026-09-25 name only the contract month and are withheld and counted (coverage.withheld_rows); non-trading days and sessions that repeat the prior one are withheld and listed. freshness.sessions_behind and stale label a late feed.","query_params":[{"name":"date","type":"string","description":"Session YYYY-MM-DD; omit for the newest"},{"name":"history","type":"int","default":20,"min":0,"max":250,"description":"Sessions of term-structure history ending at the served session"}],"admin":false,"display_name":"VIX futures curve","public_name":"volatility_vx_curve"},{"name":"tengu_v3_positioning_cot","method":"GET","path":"/api/v3/positioning/cot","group":"v3","description":"COMMITMENTS OF TRADERS, FULL DISAGGREGATED REPORT (CFTC, commodity futures only): per market, each trader category (producer/merchant, swap dealer, managed money, other reportable, total reportable, non-reportable) with long, short and spreading positions in contracts, net, weekly changes, percent of open interest, trader counts, and the 4 and 8 largest traders' concentration. report_date is the Tuesday the positions are as of; the CFTC releases it the following Friday (release_date_scheduled). Without market: the latest report's markets by open interest with each category's net (group filters, limit caps). market takes a contract market code, the exact name or a common name (GOLD, WTI): its newest `weeks` reports; ambiguous is 409, a financial future 404 market_not_in_report. History from July 2026 (coverage says). Legacy and financial-futures reports are not served; /intel/cftc_cot has four cohorts from 2006. 1h cache.","query_params":[{"name":"market","type":"string","description":"Contract market code, exact market name, or a common name (GOLD, WTI, CORN)"},{"name":"weeks","type":"int","default":8,"min":1,"max":52,"description":"Weekly reports for one market, newest first"},{"name":"group","type":"string","description":"Commodity group for the cross-section; the response lists the accepted groups"},{"name":"limit","type":"int","default":50,"min":1,"max":400,"description":"Markets in the cross-section, by open interest"}],"admin":false,"display_name":"COT trader categories","public_name":"positioning_cot"},{"name":"tengu_v3_intel_short_interest","method":"GET","path":"/api/v3/intel/short_interest/{ticker}","group":"v3","description":"FINRA bi-monthly short interest: short_interest_shares, short_interest_pct_of_shares_outstanding (with shares_outstanding: the share class's own count as known on the settlement date, shares_outstanding_known_at, and its basis; short_interest_pct_of_float is null because no public-float figure is held, and a %-of-float figure runs higher), days_to_cover, short_interest_change_pct_prior_settlement (~15 days), short_interest_change_pct_30d (vs the settlement about a month earlier, change_30d_base_settlement_date), avg_daily_volume_at_settlement, and the settlement's age_days / is_stale (over 35 days). Call for 'how shorted is X?' / squeeze questions. borrow_fee_pct_annualized is null — see /intel/borrow_cost. Market-data FINRA re-publish; 6h cache.","path_params":["ticker"],"query_params":[],"admin":false,"display_name":"Short interest","public_name":"intel_short_interest"},{"name":"tengu_v3_intel_analyst_consensus","method":"GET","path":"/api/v3/intel/analyst_consensus/{ticker}","group":"v3","description":"Analyst consensus: rating_label (Strong Buy…Strong Sell), rating_score (1-5), bucket counts, price_target_avg/high/low/count (avg is the source's own mean target, not a mean of mean/high/low; price_target_count_basis says what the count counts: rating_actions | news_rating_actions | summary_fields = the source's low/mean/high, NOT analysts; price_target_analysts is the number of analysts behind the targets when the source says, else null), recent_actions[] (upgrades/downgrades/PT changes, firm+analyst+from→to; recent_action_limit). Call for 'what do analysts say about X?' / price targets. Actions from newswire (client-side ticker filter). 1h cache.","path_params":["ticker"],"query_params":[{"name":"recent_action_limit","type":"int","default":10,"min":1,"max":50,"description":"Number of recent rating actions to return."}],"admin":false,"display_name":"Analyst coverage","public_name":"intel_analyst_consensus"},{"name":"tengu_v3_intel_borrow_cost","method":"GET","path":"/api/v3/intel/borrow_cost/{ticker}","group":"v3","description":"Securities-lending borrow cost (annualized fee %, rebate, utilization, shares available) — LIVE. Source chain, first hit wins (see `source`): 1) the options-flow feed's shorts data (intraday) + recent SEC fails-to-deliver (ftd_recent, with data_through, age_days and is_stale: the SEC publishes twice a month, weeks behind); 2) the securities-finance archive's latest daily row; 3) option-implied borrow. The shorts feed reports availability only up to 10,000,000 shares: at that ceiling short_shares_available is null, availability_capped is true and short_shares_available_min is 10,000,000. `is_stale` flags prints older than 48h (archive rows trail on the archive's refresh lag). data_source_pending=true ONLY when all three sources miss — then fall back to /intel/short_interest as the squeeze proxy. Use /intel/borrow_cost_history for the daily series. 15-min cache.","path_params":["ticker"],"query_params":[],"admin":false,"display_name":"Borrow cost","public_name":"intel_borrow_cost"},{"name":"tengu_v3_sec_filing_extract","method":"GET","path":"/api/v3/sec/filing/{ticker}/{filing_type}","group":"v3","description":"The company's latest 10-K, 10-Q or 8-K, read from SEC EDGAR. XBRL figures are this filing's own, read at its accession and period_of_report (each block names its accession_number and units): balance_sheet_summary (as_of), cash_flow_summary (period says which: a 10-K's fiscal year, a 10-Q's fiscal year to date; free_cash_flow_proxy is operating cash flow less capital_expenditures, or operating plus investing cash flow where the filing tags no capex: free_cash_flow_basis), shares_outstanding (a 10-Q's quarter, a 10-K's year; diluted_trend_4q: one three-month value per quarter end, as known when the filing was made, each with the accession_number that reported it). xbrl_facts_status: ok; not_in_company_facts when EDGAR's company facts attribute no figures to this accession (an 8-K, or a filing EDGAR has not attributed yet), the blocks then null; not_in_usd when its figures are in another currency (xbrl_facts_currency). latest_company_snapshot holds the newest figures EDGAR attributes to the company when another filing reported them, which can be earlier or later than this one (period_relative_to_this_filing), with that filing's accession_number, form, filed and its own as_of; null when this filing holds them. filing_date, filing_url, accession_number, accession_index_url (this filing's documents). text_sections holds the filing's own narrative sections, text verbatim from the filing: 10-K business (Item 1), risk_factors (1A), mda_discussion (7), quantitative_market_risk (7A); 10-Q mda_discussion (Part I Item 2), quantitative_market_risk (Part I Item 3), risk_factors (Part II Item 1A); both material_subsequent_events (the Subsequent Events note; most filings have none: not_found). An 8-K has none of them. Text comes only for the sections named in sections (comma list, or all); without it each section carries its status, heading and chars_total with text null, so call again with sections=<name> to read it. Each section: status (extracted, no_material_changes: a 10-Q item saying nothing changed since the 10-K, incorporated_by_reference: the text is the filing's pointer to where the section is, not_found, not_applicable, source_unavailable: retry, available_on_request: not read yet), heading, text, chars_total, offset, chars_returned, truncated, next_offset. Page a long section by calling again with that one section and offset=its next_offset (offset takes a single section). An incorporated_by_reference section says where it points (points_to: annual_report_exhibit, annual_report_10k, same_filing, other_document). A section a 10-K takes from its Exhibit 13 annual report, from pages it names, or from its own cross-reference index, is read from there when it can be (document_url, reference). text_sections._status: extracted, partial, not_extracted or available_on_request; note says what to do when a section is missing. XBRL part cached 24h.","path_params":["ticker","filing_type"],"query_params":[{"name":"sections","type":"string","description":"comma list of sections whose text to return, or all: risk_factors, mda_discussion, quantitative_market_risk, business, material_subsequent_events. Omitted: status and length only, no text"},{"name":"max_chars","type":"int","default":12000,"min":1000,"max":60000,"description":"characters of text per named section in this response"},{"name":"offset","type":"int","default":0,"min":0,"max":10000000,"description":"character offset into the one section named in sections (offset needs exactly one); pass its next_offset to read its next page"}],"admin":false,"display_name":"SEC filing detail","public_name":"sec_filing_extract"},{"name":"tengu_v3_research_portfolio_aware_score","method":"POST","path":"/api/v3/research/portfolio_aware_score","group":"v3","description":"Adjusts a candidate's standalone score for the user's portfolio. Send the candidate's standalone score (e.g. from the copilot score tool) and the user's holdings; the answer is the overlay: concentration_penalty (single-name cap, default 15%), sector_cap_penalty (sector cap, default 30%; the sector is the SIC industry mapped to a GICS-style sector, an approximation stated in sector_basis, unless candidate_sector or holding sectors are passed; sector_cap_applied is false, with sector_unknown_holdings, when a weighted holding has no known sector), correlation_to_existing (top 5 holdings by |rho|, daily log returns aligned on shared dates over ~3 years, n_overlap_days per holding; holdings whose correlation could not be read are in correlation_unavailable with a reason), tax_lot_warnings (short-term gains, from each holding's purchase_date), and a rebalance_recommendation (action swap, trim_only, buy_naked or hold_no_add, with sell/buy/sector blocks). total_penalty multiplies the standalone score down to portfolio_aware_score. Use it only when you have the user's holdings.","body_params":[{"name":"ticker","type":"string","required":true},{"name":"user_holdings","type":"array","required":true,"description":"Array of {ticker, weight_pct, cost_basis, purchase_date, sector?} — sector hint optional (a GICS sector name; any other value is listed in sector_hints_ignored), endpoint resolves via the market-data provider if missing"},{"name":"standalone_score","type":"object","required":true,"description":"{decile: int, score: float in [0,1], verdict_label: str} — from the same-turn copilot_score_ticker call"},{"name":"candidate_sector","type":"string","required":false,"description":"Optional sector for the ticker: one of the 11 GICS sector names (case-insensitive; common synonyms such as Technology or Healthcare are accepted; any other value is a 400 listing them). Otherwise derived from its SIC industry, an approximation of GICS"},{"name":"cash_pct","type":"float","required":false},{"name":"total_portfolio_value","type":"float","required":false},{"name":"caps","type":"object","required":false,"description":"{single_name_pct: float (default 15.0), sector_pct: float (default 30.0)} — override the institutional default risk caps"}],"admin":false,"display_name":"Score for your portfolio","body_schema":{"type":"object","required":["ticker","user_holdings","standalone_score"],"additionalProperties":false,"properties":{"ticker":{"type":"string","minLength":1,"description":"candidate ticker"},"user_holdings":{"type":"array","minItems":1,"description":"current positions; weights sum to at most 100","items":{"type":"object","required":["ticker","weight_pct"],"additionalProperties":false,"properties":{"ticker":{"type":"string","minLength":1},"weight_pct":{"type":"number","minimum":0,"description":"percent of the portfolio (8.2 = 8.2%)"},"cost_basis":{"type":["number","null"],"description":"cost basis, USD per share"},"purchase_date":{"type":["string","null"],"description":"YYYY-MM-DD; flags a short-term tax lot"},"sector":{"type":["string","null"],"description":"optional GICS sector hint"}}}},"standalone_score":{"type":"object","required":["decile","score"],"additionalProperties":false,"description":"the candidate's standalone score, e.g. from the copilot score tool","properties":{"decile":{"type":"integer","minimum":1,"maximum":10},"score":{"type":"number","minimum":0,"maximum":1},"verdict_label":{"type":["string","null"]}}},"cash_pct":{"type":["number","null"],"minimum":0,"description":"cash, percent of the portfolio; accepted, not used by the overlay"},"total_portfolio_value":{"type":["number","null"],"minimum":0,"description":"portfolio value, USD; accepted, not used by the overlay"},"caps":{"type":["object","null"],"additionalProperties":false,"description":"override the default risk caps","properties":{"single_name_pct":{"type":["number","null"],"exclusiveMinimum":0,"description":"single-name cap, percent (default 15)"},"sector_pct":{"type":["number","null"],"exclusiveMinimum":0,"description":"sector cap, percent (default 30)"}}}}},"public_name":"research_portfolio_aware_score"},{"name":"tengu_v3_research_scenario_simulator","method":"POST","path":"/api/v3/research/scenario_simulator","group":"v3","description":"Deterministic DCF-style projection under bull, base and bear (or your own) scenarios. You supply the TTM financials and, per scenario, revenue_growth_pct, net_margin_pct and exit_pe_multiple; it projects over horizon_quarters (default 4) and returns projected_revenue, projected_eps, projected_price, implied_upside_pct and implied_cagr_pct per scenario, each with a math_trail of the steps. The summary gives a probability-weighted expected_value_price, a skew label and the bull/bear asymmetry_ratio. Pure arithmetic on your inputs: no model, no market data.","body_params":[{"name":"ticker","type":"string","required":true},{"name":"current","type":"object","required":true,"description":"TTM financials: revenue_ttm, eps_ttm, shares_outstanding, current_price"},{"name":"scenarios","type":"object","required":true,"description":"Map of scenario_name → {revenue_growth_pct, net_margin_pct, exit_pe_multiple}"},{"name":"horizon_quarters","type":"int","required":false,"default":4,"description":"Projection horizon in quarters (1-40)"},{"name":"scenario_probabilities","type":"object","required":false,"description":"Optional map of scenario_name → probability (normalized internally); enables EV summary"}],"admin":false,"display_name":"Scenarios","body_schema":{"type":"object","required":["ticker","current","scenarios"],"additionalProperties":false,"properties":{"ticker":{"type":"string","minLength":1,"description":"ticker the projection is for"},"current":{"type":"object","required":["revenue_ttm","shares_outstanding","current_price"],"additionalProperties":false,"description":"trailing-twelve-month starting point you supply","properties":{"revenue_ttm":{"type":"number","exclusiveMinimum":0,"description":"TTM revenue, USD"},"eps_ttm":{"type":["number","null"],"description":"TTM diluted EPS, USD per share"},"shares_outstanding":{"type":"number","exclusiveMinimum":0,"description":"shares outstanding, count"},"current_price":{"type":"number","exclusiveMinimum":0,"description":"current share price, USD"}}},"scenarios":{"type":"object","minProperties":1,"description":"scenario name (e.g. bull, base, bear) -> assumptions","additionalProperties":{"type":"object","required":["revenue_growth_pct","net_margin_pct","exit_pe_multiple"],"additionalProperties":false,"properties":{"revenue_growth_pct":{"type":"number","description":"annual revenue growth, percent (25 = 25%)"},"net_margin_pct":{"type":"number","description":"net margin at the horizon, percent"},"exit_pe_multiple":{"type":"number","description":"price/earnings multiple at the horizon, x"}}}},"horizon_quarters":{"type":["integer","null"],"minimum":1,"maximum":40,"default":4,"description":"projection horizon, quarters"},"scenario_probabilities":{"type":["object","null"],"additionalProperties":{"type":"number","minimum":0},"description":"optional scenario name -> probability (normalised to sum to 1); enables the probability-weighted summary"}}},"public_name":"research_scenario_simulator"},{"name":"tengu_v3_intel_calendar_economics","method":"GET","path":"/api/v3/intel/calendar/economics","group":"v3","description":"US macro release calendar from official schedules: FRED's release calendar (BLS, BEA, Census, Fed and Labor Department dates) and the Fed's FOMC calendar, as far ahead as the agencies have published dates (coverage.complete_through). One row per headline: CPI, core CPI, payrolls, unemployment, GDP, PCE prices, retail sales, PPI, jobless claims, JOLTS, industrial production, housing, durable goods, trade, ECI, ADP, sentiment, FOMC decisions. Each row: date, the agency's usual time (ET), actual (the value published that day) and prior, actual_status scheduled | released | pending | not_in_source | not_read. consensus is always null; for forecasts of the last 30 days' releases call tengu_v3_news_forex_economic_calendar. importance 1-3, 3 = market-moving. Default: today onward. Days back ~13 months use the same sources; older windows, and countries other than USA, read an archive ending June 2026. A failed schedule read is a 503, not billed.","query_params":[{"name":"country","type":"string","description":"USA (or US) or none: the official US schedule; another ISO-3 code reads only the archive"},{"name":"date_from","type":"string","description":"YYYY-MM-DD"},{"name":"date_to","type":"string","description":"YYYY-MM-DD"},{"name":"importance","type":"int","min":0,"max":5,"description":"minimum importance; on the official schedule a tier 1-3 (3 = market-moving), 4 and 5 read as 3"},{"name":"limit","type":"int","default":50,"min":1,"max":100}],"admin":false,"display_name":"Economic calendar","public_name":"intel_calendar_economics"},{"name":"tengu_v3_intel_calendar_ratings","method":"GET","path":"/api/v3/intel/calendar/ratings","group":"v3","description":"Analyst rating actions and price-target changes, live: analyst_firm, action_company (Upgrades/Downgrades/Initiates/Reiterates/Resumes), action_pt (Raises/Lowers/Maintains/Announces, from the prior and current target), pt_current, pt_prior, pt_pct_change, rating_current/prior, date and time (New York). analyst_name is null on live rows. An action filter matched over only the newest rows read says result not_found_in_rows_read or partial_scan (narrow tickers or dates). The live feed carries only part of the street's actions (feed_coverage 'partial'): most price-target changes on a maintained rating are missing, so an empty answer is result none_in_feed, never 'no analyst acted'. Call this when the user asks about upgrades, downgrades, or price-target moves on a ticker.","query_params":[{"name":"tickers","type":"string"},{"name":"date_from","type":"string","description":"YYYY-MM-DD"},{"name":"date_to","type":"string","description":"YYYY-MM-DD"},{"name":"action","type":"string","enum":["Raises","Lowers","Maintains","Announces","Initiates","Reiterates"]},{"name":"limit","type":"int","default":50,"min":1,"max":100}],"admin":false,"display_name":"Analyst calendar","public_name":"intel_calendar_ratings"},{"name":"tengu_v3_intel_calendar_conference_calls","method":"GET","path":"/api/v3/intel/calendar/conference_calls","group":"v3","description":"Earnings-call schedule per company (tickers required, at most 5): one row per earnings call with date (the call's day), period and period_year (the FISCAL period the call's title names, e.g. Q3 2026), headline and keydev_id, soonest first. Default window: today to 90 days ahead; a lone date_from or date_to opens 90 days from that date; both set any window up to 366 days (history from 1990). Read from the key-developments archive, which dates scheduled calls ahead; data_through is its newest entry day (loaded about weekly, is_stale past 21 days), so a call scheduled after it may be missing and an empty answer carries empty_reason. start_time, dial-in numbers, access codes, webcast_url, importance, updated and notes are not carried (null; fields_not_carried lists them); the importance filter is refused (422). Call it for 'when is X's next earnings call?'.","query_params":[{"name":"tickers","type":"string","required":true,"description":"Comma-separated symbols, at most 5"},{"name":"date_from","type":"string","description":"YYYY-MM-DD"},{"name":"date_to","type":"string","description":"YYYY-MM-DD"},{"name":"importance","type":"int","min":0,"max":5,"description":"Not supported: any value is refused (422 unsupported_filter); this source carries no importance score."},{"name":"limit","type":"int","default":50,"min":1,"max":100}],"admin":false,"display_name":"Conference calls","public_name":"intel_calendar_conference_calls"},{"name":"tengu_v3_intel_commodities","method":"GET","path":"/api/v3/intel/commodities","group":"v3","description":"Live prices for the macro commodities (oil WTI/Brent, gold, silver, nat-gas, copper). AUTHORITATIVE source for any numeric commodity claim — call this BEFORE quoting a price level. Per item: 'spot' (the live price — quote this, in 'unit') is the FRONT-MONTH FUTURES contract for oil, natural gas and copper and the SPOT QUOTE for gold and silver; 'spot_basis' ('front_month_future' | 'spot_fx' | 'unavailable', then 'spot_reason' says why); 'contract' (futures: contract_ticker, delivery_month, last_trade_date, dte, selection — name the contract when quoting, and near expiry say so; a contract already in its delivery month is skipped, and one that settled its final session today is replaced by the next, named in rolled_from. Otherwise, on a contract's last trade date, final_session_settled is false (no final settlement published yet), null (its settlement was not in what could be read on the call) or true (it settled and no later contract is listed), and next_contract names the contract that follows); 'spot_time' (when it traded or was quoted); 'is_stale' (spot older than 80 h); 'unit' (USD/barrel oil, USD/MMBtu gas, USD/troy ounce gold and silver, USD/pound copper). 'change_pct_1d/5d/30d' compare spot with the same contract's settlement (futures) or the daily close (metals) one session, five sessions and 30 calendar days earlier; 'changes' gives each reference price and date, or a reason when a window is not reached; 'prior' is the 1d reference; 'history_5d' the last six settlements/closes, oldest first. 'official_close' + 'official_close_as_of' + 'official_close_unit' is the dated official physical-spot price (copper: a monthly average in USD/metric ton), published days to weeks late and never scaled to today — quote it only when the user asks for that official print, with its date. 'etf_proxy_quote' is a related fund's share price, reference only. 'live_spot_estimate' equals 'spot'; 'bridge_return_pct' is always null. 'symbol=oil' returns both WTI and Brent; default 'all' returns all six.","query_params":[{"name":"symbol","type":"string","default":"all","enum":["all","oil","wti_oil","brent_oil","gold","silver","natgas","copper"]}],"admin":false,"display_name":"Commodities","public_name":"intel_commodities"},{"name":"tengu_v3_news_crypto_latest","method":"GET","path":"/api/v3/news_crypto/latest","group":"v3","description":"Recent crypto news for one or more symbols: title, source, date, topic tags, and the vendor's own per-article sentiment label as vendor_sentiment_label_untrusted (an unvalidated label, not a signal; sentiment_label_policy says why). PRIMARY tool for ticker-specific crypto drilling (BTC, ETH, SOL, COIN, MSTR) — call when the user asks what's happening with a specific coin; use by_category for market-wide questions. 180s cache.","query_params":[{"name":"tickers","type":"string","required":true,"description":"Comma-separated symbols, e.g. 'BTC,ETH'"},{"name":"items","type":"int","default":20,"min":1,"max":50},{"name":"date_range","type":"string","default":"today","enum":["today","yesterday","last7days","last30days"]},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional: this tool serves crypto only, so crypto is the one value."}],"admin":false,"display_name":"Crypto news (latest)","public_name":"news_crypto_latest"},{"name":"tengu_v3_news_crypto_by_category","method":"GET","path":"/api/v3/news_crypto/by_category","group":"v3","description":"Crypto news by section: section='general' for overall crypto-market headlines, section='alltickers' for cross-coin coverage. PRIMARY tool for broad 'what's happening in crypto today' questions — for a single coin use news_crypto_latest instead. 120s cache. A 503 (e.g. upstream_quota_exhausted, with retry_after_s) means the feed could not be read, not that there is no crypto news.","query_params":[{"name":"section","type":"string","default":"general","enum":["general","alltickers"]},{"name":"items","type":"int","default":20,"min":1,"max":50},{"name":"date_range","type":"string","default":"today"},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional: this tool serves crypto only, so crypto is the one value."}],"admin":false,"display_name":"Crypto news by category","public_name":"news_crypto_by_category"},{"name":"tengu_v3_news_crypto_sentiment_stats","method":"GET","path":"/api/v3/news_crypto/sentiment_stats","group":"v3","description":"crypto-news: daily sentiment rollup for a crypto symbol (-1.5 to +1.5). Densest single-call signal — N days of (positive_count, negative_count, neutral_count, sentiment_score). Use to detect sentiment regime shifts on BTC/ETH/etc. 300s cache.","query_params":[{"name":"ticker","type":"string","required":true,"description":"Crypto symbol, e.g. BTC, ETH, SOL"},{"name":"date_range","type":"string","default":"last30days","enum":["last7days","last30days","last60days"]},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional: this tool serves crypto only, so crypto is the one value."}],"admin":false,"display_name":"Crypto sentiment stats","public_name":"news_crypto_sentiment_stats"},{"name":"tengu_v3_news_crypto_market_sentiment","method":"GET","path":"/api/v3/news_crypto/market_sentiment","group":"v3","description":"Overall crypto market sentiment rollup across the news feed (no ticker filter). Call this when the user asks whether crypto as a whole looks bullish or bearish right now — for a specific coin's sentiment use news_crypto_latest. 300s cache.","query_params":[{"name":"date_range","type":"string","default":"last7days"},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional: this tool serves crypto only, so crypto is the one value."}],"admin":false,"display_name":"Crypto sentiment (overall)","public_name":"news_crypto_market_sentiment"},{"name":"tengu_v3_news_crypto_trending","method":"GET","path":"/api/v3/news_crypto/trending","group":"v3","description":"Trending crypto headlines, noise-filtered down to top stories only. Pass ticker to filter to one coin; omit for market-wide trending. Call this when the user asks what the biggest crypto stories are right now. 120s cache.","query_params":[{"name":"ticker","type":"string","description":"Optional crypto symbol filter"},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional: this tool serves crypto only, so crypto is the one value."}],"admin":false,"display_name":"Crypto trending (movers)","public_name":"news_crypto_trending"},{"name":"tengu_v3_news_crypto_ticker_only","method":"GET","path":"/api/v3/news_crypto/ticker_only","group":"v3","description":"Crypto news mentioning ONLY the requested coin, with no co-tagged altcoins — the strictest per-coin filter. Call this when the user wants pure single-coin coverage and news_crypto_latest brings back too much cross-coin noise.","query_params":[{"name":"ticker","type":"string","required":true},{"name":"items","type":"int","default":50,"min":1,"max":100},{"name":"page","type":"int","default":1,"min":1,"max":50},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional: this tool serves crypto only, so crypto is the one value."}],"admin":false,"display_name":"Crypto news (ticker only)","public_name":"news_crypto_ticker_only"},{"name":"tengu_v3_news_crypto_multi_ticker","method":"GET","path":"/api/v3/news_crypto/multi_ticker","group":"v3","description":"Crypto news where ALL the listed coins co-appear in the same story — a correlation feed. Call this when the user asks how two or more coins are linked in the news, e.g. stories covering both BTC and ETH together.","query_params":[{"name":"tickers","type":"string","required":true},{"name":"items","type":"int","default":50,"min":1,"max":100},{"name":"page","type":"int","default":1,"min":1,"max":50},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional: this tool serves crypto only, so crypto is the one value."}],"admin":false,"display_name":"Crypto news (multi-ticker)","public_name":"news_crypto_multi_ticker"},{"name":"tengu_v3_news_crypto_all_tickers_sentiment","method":"GET","path":"/api/v3/news_crypto/all_tickers_sentiment","group":"v3","description":"Sentiment leaderboard across the full tracked crypto universe — every coin's sentiment_score over the window (default last7days). Call this when the user asks which coins have the most bullish or most bearish news sentiment right now.","query_params":[{"name":"date_range","type":"string","default":"last7days"},{"name":"page","type":"int","default":1,"min":1,"max":20},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional: this tool serves crypto only, so crypto is the one value."}],"admin":false,"display_name":"Crypto sentiment per ticker","public_name":"news_crypto_all_tickers_sentiment"},{"name":"tengu_v3_news_crypto_top_mentions","method":"GET","path":"/api/v3/news_crypto/top_mentions","group":"v3","description":"Top 50 most-mentioned crypto tickers over the window (default last7days) — a crypto-attention proxy. Call this when the user asks which coins are getting the most buzz or news coverage lately.","query_params":[{"name":"date_range","type":"string","default":"last7days"},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional: this tool serves crypto only, so crypto is the one value."}],"admin":false,"display_name":"Crypto trending (mentions)","public_name":"news_crypto_top_mentions"},{"name":"tengu_v3_news_crypto_events","method":"GET","path":"/api/v3/news_crypto/events","group":"v3","description":"Clustered crypto headline events — related stories grouped into discrete events; fetch recent events, filter by ticker, or drill into one eventid. Call this when the user asks what distinct news events hit a coin rather than a raw headline list.","query_params":[{"name":"tickers","type":"string"},{"name":"eventid","type":"string"},{"name":"page","type":"int","default":1,"min":1,"max":20},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional: this tool serves crypto only, so crypto is the one value."}],"admin":false,"display_name":"Crypto events","public_name":"news_crypto_events"},{"name":"tengu_v3_news_crypto_sundown","method":"GET","path":"/api/v3/news_crypto/sundown","group":"v3","description":"Evening crypto market-recap digest, published Mon-Fri at 7pm ET. Call this when the user asks for an end-of-day crypto wrap-up or a morning briefing needs an overnight crypto recap.","query_params":[{"name":"page","type":"int","default":1,"min":1,"max":10},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional: this tool serves crypto only, so crypto is the one value."}],"admin":false,"display_name":"Crypto evening digest","public_name":"news_crypto_sundown"},{"name":"tengu_v3_news_crypto_ticker_price","method":"GET","path":"/api/v3/news_crypto/ticker_price","group":"v3","description":"Delayed crypto prices with 24h volume and price changes — a single coin, a list, or the top 50 by 24h volume when tickers is omitted. Call this when the user asks where a coin is trading or which coins are moving; prices are delayed, not real-time. Each row adds as_of, price_age_seconds and is_stale from the vendor time (stale after 15 minutes, or when that time is missing). The price is still returned.","query_params":[{"name":"tickers","type":"string","description":"Omit for top 50 by 24h volume"},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional: this tool serves crypto only, so crypto is the one value."}],"admin":false,"display_name":"Crypto price","public_name":"news_crypto_ticker_price"},{"name":"tengu_v3_news_crypto_whale_transactions","method":"GET","path":"/api/v3/news_crypto/whale_transactions","group":"v3","description":"Large crypto on-chain and exchange transactions for BTC/ETH/SOL/TRX plus major exchanges, filterable by min_amount USD (updated ~every 5min). Call this when the user asks about whale moves or big transfers; use whale_summary for the aggregated buy-vs-sell read.","query_params":[{"name":"tickers","type":"string"},{"name":"date_range","type":"string","default":"last24hours"},{"name":"min_amount","type":"int","min":0,"description":"Minimum USD value (e.g. 5000000)"},{"name":"items","type":"int","default":50,"min":1,"max":100},{"name":"page","type":"int","default":1,"min":1,"max":20},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional: this tool serves crypto only, so crypto is the one value."}],"admin":false,"display_name":"Whale watch (transactions)","public_name":"news_crypto_whale_transactions"},{"name":"tengu_v3_news_crypto_whale_summary","method":"GET","path":"/api/v3/news_crypto/whale_summary","group":"v3","description":"Aggregated whale-transaction stats over the window: total volume, net exchange flow (in vs out), and biggest single tx. PRIMARY tool for 'is smart money buying or selling this coin?' — use whale_transactions for the individual transfers.","query_params":[{"name":"tickers","type":"string"},{"name":"date_range","type":"string","default":"last7days"},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional: this tool serves crypto only, so crypto is the one value."}],"admin":false,"display_name":"Whale watch (summary)","public_name":"news_crypto_whale_summary"},{"name":"tengu_v3_crypto_derivatives_funding","method":"GET","path":"/api/v3/crypto/derivatives/funding","group":"v3","description":"Call this when you need to know whether a coin's perp market is CROWDED — cross-venue perpetual funding for up to 20 base assets (default: top-20 coins by open interest across the first-party venues). Seven venues are read first-party (tier 'verified'); a licensed aggregator adds the venues this region cannot reach (tier 'aggregator') only after its units are calibrated against the verified venues on every call and each row passes plausibility, price and asset-class checks — every row names its source. Every rate is normalised to an 8h-equivalent from each venue's OWN settlement interval (venues mix 1h/4h/8h); a row whose interval had to be assumed says interval_assumed and stays out of the *_all aggregates. funding_rate_8h is the OI-weighted rate over verified venues (funding_rate_basis says so; the plain mean is mean_rate_8h_verified); when a verified venue quotes a rate but its OI read is missing, the headline switches to the verified median, labelled by funding_rate_basis and stored under its own signal name; oi_weighted_rate_8h and dispersion_bps are verified too; *_all keys add the aggregator tier. Also: median, OI concentration (oi_hhi), coverage, divergence flags, APR, and a 30-day z-score of one venue's rate against its own settlements once ≥60 exist (funding_z_venue names it). The answer is shaped to stay under 15k chars: for several coins rows[].venues is {venue: rate_8h} over verified venues and venues_aggregator over the aggregator rows that enter the aggregates (shape and budget say what was served); detail=full is meant for ONE coin: every per-venue field and the flat `venues` list. Perps a venue declares as a stock, ETF, index, FX or commodity are refused; a coin-and-commodity token (e.g. gold-backed) is served labelled commodity_backed_token; a coin no venue classifies is served labelled asset_class: unknown. Missing is typed with a reason, never zero. coverage.not_covered names the venues in no value here (with a reason_code) and coverage.headline_scope what the headline covers, so no total is market-wide. DATA context (not_a_score, not_a_forecast) — rich funding is crowding in one regime and trend confirmation in another. Auth: X-API-Key.","query_params":[{"name":"symbols","type":"string","description":"Comma list of BASE assets (BTC,ETH,SOL — never BTC-USD), ≤20. Omit for top-20 by OI."},{"name":"asset_class","type":"string","default":"crypto","enum":["crypto"],"description":"This route is crypto-native. asset_class=crypto is accepted."},{"name":"detail","type":"string","default":"auto","enum":["auto","full","summary"],"description":"auto = shaped to stay under 15k chars (flat per-venue rows for one coin; compact {venue: value} maps for several); full = every field, for ONE coin; summary = no flat rows."}],"admin":false,"display_name":"Crypto funding (cross-venue)","public_name":"crypto_derivatives_funding"},{"name":"tengu_v3_crypto_derivatives_open_interest","method":"GET","path":"/api/v3/crypto/derivatives/open_interest","group":"v3","description":"Call this for LEVERAGE in the system — perpetual open interest per base asset in USD: oi_usd_total over the venues read first-party, oi_usd_total_all adding the calibrated aggregator tier (an aggregator venue's OI above 3× the largest verified venue's is capped and flagged), the per-venue breakdown, the dominant verified venue and OI concentration (oi_hhi). USD is the ONLY unit summed cross-venue (base-coin OI stays per venue; contract counts are never served because contract size varies 0.01→1000 across symbols). Venues this region cannot reach appear only through the aggregator tier, and the sources block says which (geo_blocked when it is off) rather than reporting a smaller total as if it were the whole market. Pair with derivatives_funding: rising OI + rising funding = new longs; rising OI + falling price = new shorts. DATA context, not a score. Auth: X-API-Key.","query_params":[{"name":"symbols","type":"string","description":"Comma list of BASE assets, ≤20"},{"name":"asset_class","type":"string","default":"crypto","enum":["crypto"],"description":"This route is crypto-native. asset_class=crypto is accepted."},{"name":"detail","type":"string","default":"auto","enum":["auto","full","summary"],"description":"auto = shaped to stay under 15k chars (flat per-venue rows for one coin; compact {venue: value} maps for several); full = every field, for ONE coin; summary = no flat rows."}],"admin":false,"display_name":"Crypto open interest","public_name":"crypto_derivatives_open_interest"},{"name":"tengu_v3_crypto_derivatives_basis","method":"GET","path":"/api/v3/crypto/derivatives/basis","group":"v3","description":"Call this to read CARRY — perpetual premium (mark vs oracle/index) in basis points per venue read first-party, and the cross-venue mean. Positive = perps rich to spot (long crowding; carry available to hedged shorts). Negative = perps cheap (short crowding). Context flag, never directional on its own. not_a_score, not_a_forecast. Auth: X-API-Key.","query_params":[{"name":"symbols","type":"string","description":"Comma list of BASE assets, ≤20"},{"name":"asset_class","type":"string","default":"crypto","enum":["crypto"],"description":"This route is crypto-native. asset_class=crypto is accepted."},{"name":"detail","type":"string","default":"auto","enum":["auto","full","summary"],"description":"auto = shaped to stay under 15k chars (flat per-venue rows for one coin; compact {venue: value} maps for several); full = every field, for ONE coin; summary = no flat rows."}],"admin":false,"display_name":"Crypto perp basis","public_name":"crypto_derivatives_basis"},{"name":"tengu_v3_crypto_events_announcements","method":"GET","path":"/api/v3/crypto/events/announcements","group":"v3","description":"Call this to know WHAT an exchange announced and WHEN — listings, delistings and trading-caution flags pulled from seven venues' own announcement APIs (Korean, US and offshore), each carrying the venue's ORIGIN timestamp, FIRM's first read of it (detected_ts) and the gap between them (lag_ms; null with lag_ms_reason when the notice was up before FIRM began reading the venue), plus the notice's age (age_ms). A listing moves an asset 20-80% inside five minutes, so a news article about one is history; this is the print itself. Rows are one per (asset, event type): a notice naming five assets is five rows, and announcement_count counts the notices. Cross-venue events are collapsed with the EARLIEST origin kept and every venue listed — three exchanges delisting one asset within an hour is a materially different event from one doing so. One venue is unreachable from this region and is typed geo_blocked rather than allowed to read as 'nothing listed'. Filter by hours, event_type or symbols. DATA context (not_a_score, not_a_forecast) — an announcement is a fact, not a direction. Auth: X-API-Key.","query_params":[{"name":"hours","type":"int","default":24,"min":1,"max":168,"description":"Look-back window"},{"name":"event_type","type":"string","enum":["listing","delisting","caution","other"],"description":"Filter to one class"},{"name":"symbols","type":"string","description":"Comma list of BASE assets (BTC,ETH)"},{"name":"asset_class","type":"string","default":"crypto","enum":["crypto"],"description":"This route is crypto-native. asset_class=crypto is accepted."}],"admin":false,"display_name":"Exchange listings & delistings","public_name":"crypto_events_announcements"},{"name":"tengu_v3_crypto_events_headlines","method":"GET","path":"/api/v3/crypto/events/headlines","group":"v3","description":"Call this for what is BREAKING on crypto-native social and blogs right now, already mapped to coins. Sourced from the accounts that break events — exchange officials, security firms, tier-1 desks — with the post's own timestamp, so it runs minutes to hours ahead of any article. Every item is classified (exploit / halt / depeg / regulatory / listing / delisting / etf / unlock / liquidation) and tagged tier 1 or 2 by whether the account is a known breaking source; tier1_only=true keeps just those. A post matching no class is a plain 'headline', and a coin is tagged only when the post names it (a cashtag, a ticker or the coin's name). Retweets and replies are dropped and an account's re-posts of one post fold into the first (n_reposts) — an event is the original post, not the 400 accounts quoting it. lag_ms is how late FIRM first read the post, age_ms its age. The classification is an event TYPE, never a direction: read the price for that. DATA context, not a score. Auth: X-API-Key.","query_params":[{"name":"limit","type":"int","default":50,"min":1,"max":200},{"name":"event_type","type":"string","enum":["exploit","halt","depeg","regulatory","listing","delisting","etf","unlock","liquidation","headline"]},{"name":"symbols","type":"string","description":"Comma list of BASE assets"},{"name":"tier1_only","type":"bool","default":false,"description":"Only accounts that BREAK events"},{"name":"asset_class","type":"string","default":"crypto","enum":["crypto"],"description":"This route is crypto-native. asset_class=crypto is accepted."}],"admin":false,"display_name":"Crypto breaking headlines","public_name":"crypto_events_headlines"},{"name":"tengu_v3_crypto_onchain_flows","method":"GET","path":"/api/v3/crypto/onchain/flows","group":"v3","description":"Call this for the numbers that cannot be spun — stablecoin issuance and lending liquidations read straight off the chain. SCOPE: Ethereum mainnet only (USDC and USDT mint/burn logs, the Aave v3 pool; `scope` in the payload). Net Ethereum-mainnet USDC+USDT issuance is a PARTIAL read of stablecoin dry powder: most USDT circulates on Tron and much USDC on Solana and Base, none of which is read here. Liquidation counts are a deleveraging/stress read. Both come from raw logs, so a headline claiming a whale moved money can be checked against the transfer itself. HONESTY RULE: net supply is WITHHELD (null, net_status='partial') unless every leg answered — a failed mint query beside a successful burn query would otherwise report a large FALSE contraction, i.e. a fake risk-off. Zero liquidations is reported alongside a live pool-log count so a calm market is distinguishable from a dead feed. DATA context, not a score. Auth: X-API-Key.","query_params":[{"name":"hours","type":"int","default":24,"min":1,"max":72,"description":"Look-back window"},{"name":"asset_class","type":"string","default":"crypto","enum":["crypto"],"description":"This route is crypto-native. asset_class=crypto is accepted."}],"admin":false,"display_name":"On-chain flows & liquidations","public_name":"crypto_onchain_flows"},{"name":"tengu_v3_crypto_derivatives_vol_surface","method":"GET","path":"/api/v3/crypto/derivatives/vol_surface","group":"v3","description":"Call this for the OPTIONS market's view — the implied-volatility surface for BTC or ETH from one full-chain read (~1,000 instruments): ATM term structure (7d/30d/90d), 10%-OTM put−call skew at 30d (a moneyness proxy, labelled as such — not delta-space), put/call open-interest ratio, max pain per expiry, plus the 30-day implied-vol index and realised vol as a VOLATILITY RISK PREMIUM: iv_rv_ratio < 1 means the market is pricing LESS movement than it is realising. Expiries with < 6 strikes are typed missing, never noise. Deep chains exist for BTC and ETH only; other currencies report thin. DATA context, not a score. Auth: X-API-Key.","query_params":[{"name":"symbol","type":"string","default":"BTC","description":"BTC or ETH (deep chains)"},{"name":"asset_class","type":"string","default":"crypto","enum":["crypto"],"description":"This route is crypto-native. asset_class=crypto is accepted."}],"admin":false,"display_name":"Crypto vol surface (options)","public_name":"crypto_derivatives_vol_surface"},{"name":"tengu_v3_crypto_history_derivatives","method":"GET","path":"/api/v3/crypto/history/derivatives","group":"v3","description":"Recorded history of cross-venue perpetual funding, open interest and basis for one base asset, one row per 15-minute recording cycle, newest first. Only rows of the current multi-venue method are served (multivenue_since); earlier rows are withheld and counted. Call it for how crowding or leverage built up over days; the live crypto_derivatives tools answer only now. Units: funding_rate_8h is a fraction per 8 hours (funding_apr = x3x365, a fraction), oi_usd_total USD, perp_premium_bps and dispersion_bps basis points, mark_px USD. licence_mode says the aggregator tier's access that cycle (commercial, unavailable, timeout, error). as_of is the newest observation; gaps lists stretches over an hour with no recording; freshness says how old the newest row is. REQUIRES date or start(+end), max 31 days; a window before the recording began is a 422. DATA context, not a score. Auth: X-API-Key.","query_params":[{"name":"symbol","type":"string","required":true,"enum":["BTC","ETH","SOL","XRP","DOGE","ADA","AVAX","LINK","LTC","DOT","BNB","HYPE","ENA","TAO","ONDO","SUI","APT","ARB","OP","NEAR"],"description":"base asset (the 20 recorded every cycle)"},{"name":"date","type":"string","description":"one UTC day YYYY-MM-DD"},{"name":"start","type":"string","description":"window start (UTC day)"},{"name":"end","type":"string","description":"window end (inclusive; max 31-day window)"},{"name":"limit","type":"int","default":3000,"min":1,"max":5000},{"name":"asset_class","type":"string","default":"crypto","enum":["crypto"],"description":"This route is crypto-native. asset_class=crypto is accepted."}],"param_constraints":[{"at_least_one_of":["date","start"]}],"capability_tags":["heavy"],"admin":false,"display_name":"Crypto derivatives history","public_name":"crypto_history_derivatives"},{"name":"tengu_v3_crypto_history_derivatives_venues","method":"GET","path":"/api/v3/crypto/history/derivatives_venues","group":"v3","description":"Recorded history of every venue row behind the cross-venue funding / open-interest / basis aggregates for one base asset (rows of the current multi-venue method only): per venue and cycle, the native and 8h-normalised funding rate (fractions), settlement interval (hours), open interest (USD), mark / index / last price, premium (basis points), tier (first-party or aggregator), the row's source (first_party or aggregator), and whether a gate quarantined it and why. Call it to rebuild an aggregate, audit one venue, or compare venues over time. Filter to one venue with venue. REQUIRES date or start(+end), max 7 days; as_of, gaps and freshness as on the aggregate tool. DATA context, not a score. Auth: X-API-Key.","query_params":[{"name":"symbol","type":"string","required":true,"description":"base asset, e.g. BTC (the 20 recorded)"},{"name":"venue","type":"string","description":"one venue code, e.g. okx"},{"name":"date","type":"string","description":"one UTC day YYYY-MM-DD"},{"name":"start","type":"string","description":"window start (UTC day)"},{"name":"end","type":"string","description":"window end (inclusive; max 7-day window)"},{"name":"limit","type":"int","default":2000,"min":1,"max":5000},{"name":"asset_class","type":"string","default":"crypto","enum":["crypto"],"description":"This route is crypto-native. asset_class=crypto is accepted."}],"param_constraints":[{"at_least_one_of":["date","start"]}],"capability_tags":["heavy"],"admin":false,"display_name":"Crypto venue history","public_name":"crypto_history_derivatives_venues"},{"name":"tengu_v3_crypto_history_vol_surface","method":"GET","path":"/api/v3/crypto/history/vol_surface","group":"v3","description":"Recorded history of the BTC or ETH options volatility surface, one row per 15-minute cycle (recorded since 2026-09-02): ATM implied vol at the expiries nearest 7, 30 and 90 days and the 90d-7d slope, the 10%-OTM put-minus-call implied-vol difference at 30 days (a moneyness measure), put/call open-interest ratio, the 30-day implied-vol index, realised vol and their ratio. Every vol figure is annualised vol points (38.3 = 38.3%). Realised vol and the ratio are served only on rows recorded from realized_vol_valid_since (earlier rows recorded an unfinished hour and are null, with the reason). Call it for how implied vol and term structure moved around an event. REQUIRES date or start(+end), max 31 days; as_of, gaps and freshness say what the recording covers. DATA context, not a score. Auth: X-API-Key.","query_params":[{"name":"symbol","type":"string","default":"BTC","enum":["BTC","ETH"]},{"name":"date","type":"string","description":"one UTC day YYYY-MM-DD"},{"name":"start","type":"string","description":"window start (UTC day)"},{"name":"end","type":"string","description":"window end (inclusive; max 31-day window)"},{"name":"limit","type":"int","default":3000,"min":1,"max":5000},{"name":"asset_class","type":"string","default":"crypto","enum":["crypto"],"description":"This route is crypto-native. asset_class=crypto is accepted."}],"param_constraints":[{"at_least_one_of":["date","start"]}],"capability_tags":["heavy"],"admin":false,"display_name":"Crypto vol surface history","public_name":"crypto_history_vol_surface"},{"name":"tengu_v3_crypto_history_events","method":"GET","path":"/api/v3/crypto/history/events","group":"v3","description":"The recorded crypto event archive (since 2026-09-02): exchange announcements (listings, delistings, trading cautions) and the crypto headline feed (exploits, halts, depegs, regulatory, ETF, unlocks, liquidations), one row per item by publication time, newest first. Each row has the publication time (as_of_ts; for an item that carried none, published_time_missing is true and as_of_ts is when it was first recorded), when it was detected and recorded, the delay (lag_ms), venue, the coins it names, title and link; headline rows carry tier 1 or 2 (1 = an account known to break events). The live event tools keep only a rolling window; this answers 'what was listed or exploited last week'. Filter by feed, event_type, symbol or venue. event_type is a class, never a direction. REQUIRES date or start(+end), max 31 days. DATA context, not a score. Auth: X-API-Key.","query_params":[{"name":"date","type":"string","description":"one UTC day YYYY-MM-DD"},{"name":"start","type":"string","description":"window start (UTC day)"},{"name":"end","type":"string","description":"window end (inclusive; max 31-day window)"},{"name":"feed","type":"string","enum":["announcements","headlines"]},{"name":"event_type","type":"string","enum":["listing","delisting","caution","other","exploit","halt","depeg","regulatory","etf","unlock","liquidation","headline"]},{"name":"symbol","type":"string","description":"base asset, e.g. SOL"},{"name":"venue","type":"string","description":"exchange code, or headline_feed"},{"name":"limit","type":"int","default":200,"min":1,"max":1000},{"name":"asset_class","type":"string","default":"crypto","enum":["crypto"],"description":"This route is crypto-native. asset_class=crypto is accepted."}],"param_constraints":[{"at_least_one_of":["date","start"]}],"capability_tags":["heavy"],"admin":false,"display_name":"Crypto event archive","public_name":"crypto_history_events"},{"name":"tengu_v3_crypto_history_onchain","method":"GET","path":"/api/v3/crypto/history/onchain","group":"v3","description":"Recorded history of on-chain flow readings (since 2026-09-02), one row per metric per 15-minute cycle: stablecoin_flows_24h (USDC and USDT minted and burned on Ethereum, USD, and their net) and aave_liquidations_24h (liquidation count on the Aave v3 Ethereum pool, with the pool's total event count so a calm market is told apart from a dead feed). Each row covers the 24 hours ending at as_of_ts, so consecutive rows overlap: never add rows together. A reading where a mint or burn query did not answer has its totals withheld (null, with the reason). Call it for how stablecoin supply or liquidations trended over days. REQUIRES date or start(+end), max 31 days. DATA context, not a score. Auth: X-API-Key.","query_params":[{"name":"metric","type":"string","enum":["stablecoin_flows_24h","aave_liquidations_24h"]},{"name":"date","type":"string","description":"one UTC day YYYY-MM-DD"},{"name":"start","type":"string","description":"window start (UTC day)"},{"name":"end","type":"string","description":"window end (inclusive; max 31-day window)"},{"name":"limit","type":"int","default":3000,"min":1,"max":5000},{"name":"asset_class","type":"string","default":"crypto","enum":["crypto"],"description":"This route is crypto-native. asset_class=crypto is accepted."}],"param_constraints":[{"at_least_one_of":["date","start"]}],"capability_tags":["heavy"],"admin":false,"display_name":"On-chain flow history","public_name":"crypto_history_onchain"},{"name":"tengu_v3_news_crypto_summary","method":"GET","path":"/api/v3/news_crypto/summary/{ticker}","group":"v3","description":"crypto-news: one-shot per-coin intel summary. Parallel-fetches recent news (24h) + 7-day sentiment stats + trending headlines. The single call to make when asked 'what's going on with BTC?' or any crypto-name analysis. Cached up to 180 s; as_of is when the summary was read. When the feed's daily call allowance is spent (it resets at 00:00 UTC) this answers the same 503 refusal as the other crypto-news tools (upstream_budget_exhausted); a copy read earlier is served only if it has data, and then says so in cached_copy.","path_params":["ticker"],"admin":false,"query_params":[{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional: this tool serves crypto only, so crypto is the one value."}],"display_name":"Crypto news (summary)","public_name":"news_crypto_summary"},{"name":"tengu_v3_news_forex_latest","method":"GET","path":"/api/v3/news_forex/latest","group":"v3","description":"Recent FX news with sentiment for one or more currency pairs: title, source, sentiment (Positive/Neutral/Negative), date, topic tags. PRIMARY tool for pair-specific drilling (EUR-USD, GBP-USD, USD-JPY, AUD-USD) — call when the user asks what's moving a specific pair; use by_category for macro themes. 180s cache.","query_params":[{"name":"pairs","type":"string","required":true,"description":"Comma-separated FX pairs, e.g. 'EUR-USD,GBP-USD'"},{"name":"items","type":"int","default":20,"min":1,"max":50},{"name":"date_range","type":"string","default":"today","enum":["today","yesterday","last7days","last30days"]}],"admin":false,"display_name":"Forex news (latest)","public_name":"news_forex_latest"},{"name":"tengu_v3_news_forex_by_category","method":"GET","path":"/api/v3/news_forex/by_category","group":"v3","description":"Macro and cross-pair FX news: section='general' = market macro (Fed, CPI, ECB, NFP, BoJ, BoE), section='alltickers' = cross-pair coverage; optional topic filter (cpi, fed, oil, gold, recession...) on general. Call this when the user asks about macro FX themes rather than one pair — use news_forex_latest for pair drilling. 300s cache.","query_params":[{"name":"section","type":"string","default":"general","enum":["general","alltickers"]},{"name":"topic","type":"string","enum":["cpi","unemployment","fed","ecb","boj","boe","gdp","inflation","war","election","oil","gold","recession","tradedeals"],"description":"Optional macro topic filter (general only)"},{"name":"items","type":"int","default":20,"min":1,"max":50},{"name":"date_range","type":"string","default":"today"}],"admin":false,"display_name":"Forex news by category","public_name":"news_forex_by_category"},{"name":"tengu_v3_news_forex_sentiment_stats","method":"GET","path":"/api/v3/news_forex/sentiment_stats","group":"v3","description":"fx-news: daily sentiment rollup for an FX pair (-1.5 to +1.5). Densest single-call signal — N days of (positive_count, negative_count, neutral_count, sentiment_score). Use to detect regime shifts on EUR-USD/GBP-USD/etc. 600s cache.","query_params":[{"name":"pair","type":"string","required":true,"description":"FX pair, e.g. EUR-USD, GBP-USD, USD-JPY"},{"name":"date_range","type":"string","default":"last30days","enum":["last7days","last30days","last60days"]}],"admin":false,"display_name":"Forex sentiment stats","public_name":"news_forex_sentiment_stats"},{"name":"tengu_v3_news_forex_market_sentiment","method":"GET","path":"/api/v3/news_forex/market_sentiment","group":"v3","description":"Overall FX market sentiment rollup (no pair filter) — gauges DXY-style market posture rather than any single pair. Call this when the user asks about broad FX market mood; use news_forex_latest for a specific pair's sentiment. 600s cache.","query_params":[{"name":"date_range","type":"string","default":"last7days"}],"admin":false,"display_name":"Forex sentiment (overall)","public_name":"news_forex_market_sentiment"},{"name":"tengu_v3_news_forex_top_mentions","method":"GET","path":"/api/v3/news_forex/top_mentions","group":"v3","description":"fx-news: most-mentioned FX pairs over a window with sentiment tilt. High-leverage 'what is the FX market talking about?' single call. 300s cache.","query_params":[{"name":"date_range","type":"string","default":"last7days","enum":["today","last7days","last30days"]}],"admin":false,"display_name":"Forex trending (mentions)","public_name":"news_forex_top_mentions"},{"name":"tengu_v3_news_forex_trending","method":"GET","path":"/api/v3/news_forex/trending","group":"v3","description":"Trending FX headlines, noise-filtered down to top stories only. Pass pair (e.g. EUR-USD) to filter; omit for market-wide trending. Call this when the user asks what the biggest FX stories are right now. 300s cache.","query_params":[{"name":"pair","type":"string","description":"Optional FX-pair filter, e.g. EUR-USD"}],"admin":false,"display_name":"Forex trending (movers)","public_name":"news_forex_trending"},{"name":"tengu_v3_news_forex_sundown_digest","method":"GET","path":"/api/v3/news_forex/sundown_digest","group":"v3","description":"Daily evening FX market summary article. Call this when the user asks for an end-of-day FX wrap-up or a morning briefing needs an overnight FX recap; optional date_range filter (today/last7days). 600s cache.","query_params":[{"name":"date_range","type":"string","description":"Optional date filter (today/last7days/...)"}],"admin":false,"display_name":"Forex evening digest","public_name":"news_forex_sundown_digest"},{"name":"tengu_v3_news_forex_events","method":"GET","path":"/api/v3/news_forex/events","group":"v3","description":"Clustered FX news events from a forex newswire — high press-coverage stories like central-bank decisions, rate hikes, and intervention rumors, optionally filtered to one pair (e.g. EUR-USD). Call this when the user asks 'what major macro events hit today' or what's moving a currency. 300s cache.","query_params":[{"name":"pair","type":"string","description":"Optional pair filter, e.g. EUR-USD"},{"name":"date_range","type":"string","default":"last7days"},{"name":"items","type":"int","default":20,"min":1,"max":50}],"admin":false,"display_name":"Forex events","public_name":"news_forex_events"},{"name":"tengu_v3_news_forex_economic_calendar","method":"GET","path":"/api/v3/news_forex/economic_calendar","group":"v3","description":"Economic calendar with actual, forecast, and previous values for macro releases (Fed/CPI/NFP/ECB) — these prints are priced-in by FX traders, so call it for any 'what did CPI print / what macro data hit this week' question. Filter by currency (USD/EUR/JPY) and importance (high/medium/low). Backward-looking only: events up to now, no schedule of releases ahead. Each row has actual_value/forecast_value/previous_value as numbers in its unit (%, K, M, B, T) and an actual_status: reported | withheld | pending | upcoming | no_print. An actual that fails a consistency check (a policy rate or consumer-price print far from both its forecast and previous) is withheld as null with actual_withheld_reason; never report a withheld or pending row as a print. Duplicate listings of a release are dropped (dropped_rows). Checks are internal, not a cross-check with the statistical agencies. 600s cache.","query_params":[{"name":"currency","type":"string","description":"ISO currency filter (e.g. USD, EUR, JPY, GBP)"},{"name":"importance","type":"string","enum":["high","medium","low"]},{"name":"date_range","type":"string","default":"last7days","enum":["today","last7days","last30days"]}],"admin":false,"display_name":"Forex calendar","public_name":"news_forex_economic_calendar"},{"name":"tengu_v3_news_forex_prices","method":"GET","path":"/api/v3/news_forex/prices","group":"v3","description":"Live FX mid prices (15-min upstream refresh): pass pairs for specific quotes (e.g. EUR-USD,GBP-USD) or base for all pairs vs one currency (base=USD). Call this when the user asks where a currency pair is trading right now. Answers only the pairs asked for; a pair asked inverted (USD-EUR) is answered as quoted (EUR-USD, see resolved), a pair not found is listed in missing_pairs with a reason, and an unquoted pair alone is a 404 pair_not_quoted. Each pair adds as_of, price_age_seconds and is_stale from last_updated (stale after 15 minutes, this feed's refresh, or when that time is missing). The price is still returned. 30s cache.","query_params":[{"name":"pairs","type":"string","description":"Comma-separated pairs, e.g. 'EUR-USD,GBP-USD'"},{"name":"base","type":"string","description":"Base-currency filter (e.g. USD)"}],"admin":false,"display_name":"Forex rates","public_name":"news_forex_prices"},{"name":"tengu_v3_news_forex_summary","method":"GET","path":"/api/v3/news_forex/summary/{pair}","group":"v3","description":"fx-news: one-shot per-pair intel summary. Parallel-fetches recent news (24h) + 7-day sentiment stats + trending headlines. The single call to make when asked 'what's going on with EUR-USD?' or any FX-pair analysis. 180s cache.","path_params":["pair"],"admin":false,"display_name":"Forex news (summary)","public_name":"news_forex_summary"},{"name":"tengu_v3_research_web_search","method":"GET","path":"/api/v3/research/web_search","group":"v3","description":"Multi-mode web search in parallel across link, cited-synthesis and social-sentiment coverage. Returns synthesized_answer, social_sentiment, citations, and a deduplicated list of links. Call this BEFORE relying on model knowledge for time-sensitive questions (markets, earnings, regulation, breaking news, macro events). 15-min LRU cache.","query_params":[{"name":"query","type":"string","required":true,"description":"Natural-language query"},{"name":"providers","type":"string","default":"links,synthesis","description":"Comma-separated coverage modes: links=link results, synthesis=cited synthesis, social=social-sentiment signal. Add 'social' for sentiment-aware queries."},{"name":"freshness","type":"string","enum":["pd","pw","pm"],"description":"Time filter — past day / week / month"},{"name":"count","type":"int","default":5,"min":1,"max":20,"description":"Results per provider"}],"admin":false,"display_name":"Web search","public_name":"research_web_search"},{"name":"tengu_v3_research_fetch_url","method":"GET","path":"/api/v3/research/fetch_url","group":"v3","description":"Read ONE page whose URL a search already returned (tengu_v3_research_web_search finds the links). NOT a search tool: never call it to discover pages. Returns the page's readable text, title, author, published date and a domain trust tier (tier 1: a release wire, or a listed issuer's own newsroom or investor-relations pages; tier 2 issuer_host_unverified: an IR-looking host on another domain). It does not read past a login or a paywall: a paywalled page may answer 200 with only its teaser. Read at most the 2-3 most load-bearing links per question. A URL no retry will read is a 422 (retryable false): url_blocked, url_not_public, page_http_error (upstream_status), page_tls_error, page_bad_response, unsupported_content_type (e.g. a PDF), page_too_large or page_redirect_failed. A timeout or server error at the page is 503 page_fetch_failed with Retry-After. A page with no readable text (one that renders only with JavaScript may have none) is 503 page_extraction_empty. None is billed; read another link then.","query_params":[{"name":"url","type":"string","required":true,"description":"Absolute http(s) URL to read — use a link returned by web_search"},{"name":"max_chars","type":"int","default":8000,"min":500,"max":10000,"description":"Max extracted characters; domain trust tier may cap lower"}],"admin":false,"display_name":"Read page","public_name":"research_fetch_url"},{"name":"tengu_v3_research_synthesis","method":"GET","path":"/api/v3/research/synthesis","group":"v3","description":"Citation-rich research synthesis (grounded LLM). Returns a concise synthesized answer plus the list of source URLs that grounded it. Use when the user wants the answer GROUNDED with explicit sources (e.g. 'summarize NVIDIA's last earnings call and link the transcript'). Distinct from web_search — this returns prose + citations, not a list of headlines.","query_params":[{"name":"query","type":"string","required":true},{"name":"system_prompt","type":"string","description":"Optional system instruction; defaults to a financial-analyst persona that cites sources."}],"admin":false,"public_name":"research_synthesis"},{"name":"tengu_v3_research_x_sentiment","method":"GET","path":"/api/v3/research/x_sentiment","group":"v3","description":"Real-time X/Twitter sentiment narrative. Pass ticker=NVDA for a focused fintwit read on a name, or query=... for a free-form social-media question. Returns a model-written narrative (is_model_output true) and any source URLs it grounded against; grounded says whether the model searched X. There is no structured bullish/bearish ratio, and prices, moves and counts in the text are not checked against market data: quote numbers from the market-data tools. Use when you want the *vibe* on a name right now (retail sentiment, breaking rumours, unusual social activity), not the news article list. When the provider does not answer it returns 503 upstream_unavailable (error_code social_sentiment_unavailable; not billed). Pro and above, 1,000 credits a call: each answer runs a live grounded search, and a repeat of the same ticker or query within 5 minutes is served from that answer and billed the same.","query_params":[{"name":"ticker","type":"string","description":"Optional ticker for ticker-targeted sentiment"},{"name":"query","type":"string","description":"Optional free-form query. Pass ticker OR query — at least one is required."}],"param_constraints":[{"at_least_one_of":["ticker","query"]}],"admin":false,"display_name":"X/Twitter sentiment","public_name":"research_x_sentiment"},{"name":"tengu_v3_intel_yield_curve","method":"GET","path":"/api/v3/intel/yield_curve","group":"v3","description":"US Treasury yield curve + recession-watch spreads + breakeven inflation. Yields (1m, 3m, 6m, 1y, 2y, 5y, 10y, 30y) come from the Treasury's own daily par curve, posted the same business day, each with as_of, source and business days behind the latest official curve; the 10Y-2Y and 10Y-3M spreads are computed from those yields of one date (with 'inverted' flags — classic recession signal); plus 5Y/10Y breakeven inflation and the trade-weighted USD index (its moves in percent, never bp). Changes: 1d from the previous business day, 5d five sessions, 30d 30 calendar days. Quote these numbers verbatim with their date (curve.label) — DO NOT recall yields from training data, which is months stale. 5-min cache. For a focused short-end + cash-park view, use tengu_v3_intel_risk_free_rate.","admin":false,"display_name":"Yield curve","public_name":"intel_yield_curve"},{"name":"tengu_v3_intel_risk_free_rate","method":"GET","path":"/api/v3/intel/risk_free_rate","group":"v3","description":"Current US T-bill yields + parked-cash quick-reference. Use this for capital-allocation responses — the model needs to compare risky vs risk-free expected return ('T-bills currently yield X% — the equity allocation must clear that hurdle'). Returns 1m/3m/6m/1y/2y/10y par yields from the Treasury's same-day curve, each with as_of, source and business days behind the latest official curve; `parked_yield_example` showing a year's income on $10k principal across tenors; and curated T-bill ETF references (SGOV, BIL, SHV) with expense ratios, the bill tenor each underlying yield is taken from (SGOV/BIL 3m, SHV 6m) and SHV's carry versus the 3-month. 5-min cache.","admin":false,"display_name":"T-bill yields","public_name":"intel_risk_free_rate"},{"name":"tengu_v3_intel_options_chain","method":"GET","path":"/api/v3/intel/options_chain/{ticker}","group":"v3","description":"Live options-chain snapshot for a ticker: per contract Greeks (delta/gamma/theta/vega), implied volatility, open interest, last quote and trade (each time-stamped), day bar with its date; filter by one expiry or an expiry range, a strike range, call/put. Nearest expiry first; complete=false + truncation_reason when more contracts match than were returned, so narrow the filters. PRIMARY tool for 'where's the gamma / IV smile / max pain by strike'. Pair with options_contract (one contract's tape), options_volume (flow) and gex (dealer positioning). 30s cache.","path_params":["ticker"],"query_params":[{"name":"expiration_date","type":"string","description":"Filter to a single expiry (yyyy-mm-dd)"},{"name":"contract_type","type":"string","enum":["call","put"],"description":"'call' or 'put' to filter one side"},{"name":"limit","type":"int","default":250,"min":1,"max":2500,"description":"max contracts returned; above 250 the chain is read in pages of 250 (at most 10) and takes longer"},{"name":"min_expiration","type":"string","description":"earliest expiry to include (yyyy-mm-dd)"},{"name":"max_expiration","type":"string","description":"latest expiry to include (yyyy-mm-dd)"},{"name":"min_strike","type":"float","min":0,"description":"lowest strike to include"},{"name":"max_strike","type":"float","min":0,"description":"highest strike to include"}],"admin":false,"display_name":"Options chain","capability_tags":["heavy"],"public_name":"intel_options_chain"},{"name":"tengu_v3_intel_options_contract","method":"GET","path":"/api/v3/intel/options_contract/{option_ticker}","group":"v3","description":"Live quote and trade tape for ONE option contract: the most recent NBBO quotes (bid/ask/sizes/midpoint) and trades (price/size/exchange/conditions), newest first, each with a UTC timestamp, plus the contract's terms. Takes the OCC symbol options_chain returns as contract_symbol (O:SPY261016C00700000). The newest activity of an illiquid or expired contract can be days old: read the stamps; expired, days_to_expiration and days_since_last_activity say whether the tape is live. Each quote adds as_of, price_age_seconds and is_stale (stale after 6 hours, the equity last-trade rule). The quote is still returned. 10s cache.","path_params":["option_ticker"],"query_params":[{"name":"limit","type":"int","default":100,"min":1,"max":1000,"description":"max quotes AND max trades returned (each)"},{"name":"include","type":"string","default":"quotes,trades","description":"'quotes', 'trades', or 'quotes,trades'"}],"admin":false,"display_name":"Option contract tape","public_name":"intel_options_contract"},{"name":"tengu_v3_intel_etf_summary","method":"GET","path":"/api/v3/intel/etf_summary/{ticker}","group":"v3","description":"One-call ETF intelligence rollup — top holdings + commodity exposure + which other v3 tools work for this ticker. Returns top constituents by weight (holdings provider), and for commodity-tracking ETFs (USO/BNO/GLD/IAU/SGOL/SLV/SIVR/UNG/BOIL/CPER) the linked FRED spot + live proxy price (fred_spot_reason when the spot is null). holdings_count is the number of holdings returned (top 25 by weight); total_holdings is the fund's line count in its newest file, captured on holdings_snapshot_date. NAV, AUM and expense ratio are not served. CALL THIS BEFORE saying 'no data' on any ETF question — most ETFs have rich underlying-level intel even when the wrapper itself doesn't trade analyst targets / insider flow.","path_params":["ticker"],"admin":false,"display_name":"ETF summary","public_name":"intel_etf_summary"},{"name":"tengu_v3_skills_ta_master","method":"GET","path":"/api/v3/skills/ta_master/{ticker}","group":"v3","description":"One-call technical read on a ticker: fuses candlestick chart (RSI/MACD/BB), GEX, max pain, options flow/volume, insider and congressional trades, and off-exchange volume into a signal list, aggregate bull/bear stance, and embedded PNG chart. Call this FIRST for 'how does the chart/setup look?' — one round-trip replaces ~8 calls. Signals use completed bars only: 'synthesis.last_bar_date' is the last one, 'bars_requested' beside 'bars_count', and a week or month still open is left out ('dropped_incomplete_bar'). The gamma signal is in shares of the underlying per $1 move. A 'components' count is null, not 0, for a feed that was not fetched or whose call failed, and 'vendor_errors' says why. A ticker no listing knows is a 404 unknown_ticker.","path_params":["ticker"],"query_params":[{"name":"interval","type":"string","default":"day","enum":["minute","hour","day","week","month"],"description":"minute|hour|day|week|month"},{"name":"bars","type":"int","default":120,"min":40,"max":400}],"admin":false,"display_name":"Technical analysis","public_name":"technical_analysis"},{"name":"tengu_v3_skills_apex_equity","method":"GET","path":"/api/v3/skills/apex_equity/{ticker}","group":"v3","description":"Apex Equity Intelligence — one-call brief for 'what do you think about $TICKER'. Fuses 13 parallel reads (bars, facts, quote, statements, insider, congress, lobbying, gov-contracts, WSB, patents, off-exchange), plus a common stock's SEC cover count and splits. Returns: 'fundamentals' (name, sector, last_price, the latest statement (filing_date, period_end, fundamentals_null_reason), ttm_* over four quarters; market_cap = market_cap_shares x market_cap_price, the close of market_cap_as_of (YYYY-MM-DD, latest completed session), on price_snapshot's share count, provisional unless market_cap_shares_status is ok; with market_cap_price null, the market data's undated figure. shares_outstanding equals market_cap_shares, every share class; share_class_shares_outstanding is the listed class alone. Notes, ETNs and warrants get no count. latest_eps and ttm_eps are BASIC EPS on today's share basis, null if the split history is unknown (ttm_eps_split_status); ttm_eps_diluted is diluted (all four quarters or null)), 'intel' (8 scalar fields — insider/congress 30d counts over trade dates (insider buys and sells are Form 4 open-market purchases and sales), ttm_lobbying_usd, ttm_gov_contract_usd, wsb_7d_mentions+sentiment, patent_filings_recent, avg_off_exchange_short_ratio_pct_30d (the short-sale share of off-exchange volume, in percent; avg_dark_pool_pct_30d is null: the off-exchange feed carries no share of total volume); each windowed field counts only rows dated inside its window, and 'intel_windows' gives each one's window, date_basis and, when it is null, a reason: layer_not_read (see vendor_errors), or rows_without_dates / page_not_newest_first / page_does_not_reach_window_start (the rows read cannot cover the window, so no count is served); a layer that was not fetched or whose call failed is null, not 0, and 'vendor_errors' says why; the same holds for the intel counts in 'components'), 'flags' (notable patterns: insider_cluster_buy/sell, retail_attention_spike, etc.), 'chart' (primary daily 120-bar candlestick PNG with RSI/MACD/BB indicators, palette-quantized to keep the tool result under 32KB), and 'charts' (a list of ADDITIONAL charts beyond the primary — currently just the hourly intraday chart; do NOT expect the daily here, it's only in 'chart'). 'components' carries raw counts of items behind each digest. 'vendor_errors' is non-empty when one of the parallel fetches failed; the rest of the payload is still usable. For full per-section detail (complete insider trade list, full income statements, etc.) call the dedicated tools tengu_v3_fundamentals_*/tengu_v3_intel_* — apex_equity is the digest, not the firehose.","path_params":["ticker"],"query_params":[],"admin":false,"display_name":"Equity profile","capability_tags":["heavy"],"response_schema":{"$defs":{"ApexEquityFundamentals":{"additionalProperties":true,"description":"The ``fundamentals`` block of ``GET /api/v3/skills/apex_equity/{ticker}``.\nThe fields declared here are typed, with their units, formats and null rules;\nthe block's other fields are described in the tool's description.","properties":{"market_cap":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"USD. When market_cap_price is non-null: exactly market_cap_shares x market_cap_price (that double-precision product, unrounded), the close of market_cap_as_of on the count price_snapshot multiplies by, so market_cap / market_cap_price x a later price re-prices it. When market_cap_price is null: the market data's own figure, which it defines as a prior session's close x its reference count (market_cap_shares, basis reference_data, when that count is known) and whose session it does not name; do not re-price it. Null when neither is available, and always when market_cap_shares is null (no count, no figure: a note, ETN, warrant, unit or fund, or a split list not read now).","title":"Market Cap"},"market_cap_price":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"USD per share: the regular-session close market_cap is computed at, on today's split basis. Null exactly when market_cap_as_of is null: no share count or no completed daily close was in hand, and market_cap (if any) is the market data's undated figure.","title":"Market Cap Price"},"market_cap_as_of":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"description":"Date (YYYY-MM-DD, the New York trading date) of the regular session whose close is market_cap_price: the latest completed session when the answer was built (today's from five minutes after the closing bell; the answer is cached up to 30 minutes). Null exactly when market_cap_price is null.","title":"Market Cap As Of"},"market_cap_shares":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Shares (whole), on today's split basis: the count market_cap is built on, every share class included. Null when no count applies: only common stock or an ADR whose reference row carries a share count of its own gets one (a note, ETN, warrant, unit or preferred listed under its issuer's filings gets none), and none without a split list read now (market_cap_shares_status says why).","title":"Market Cap Shares"},"market_cap_shares_basis":{"anyOf":[{"enum":["cover_page","reference_data","balance_sheet_period_end","latest_quarter_weighted_average_basic"],"type":"string"},{"type":"null"}],"description":"Which count market_cap_shares is, as price_snapshot names it: cover_page (the latest 10-Q/10-K cover, every issued share), reference_data (the market data's count, every class as converted to this listing's), balance_sheet_period_end, or latest_quarter_weighted_average_basic. Null exactly when market_cap_shares is null.","title":"Market Cap Shares Basis"},"market_cap_shares_as_of":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"description":"Date (YYYY-MM-DD) the count is as of: the cover date for cover_page, the day the reference count was read for reference_data, the period end for the balance sheet and the weighted average. Null when market_cap_shares is null or its date is unknown.","title":"Market Cap Shares As Of"},"market_cap_shares_status":{"anyOf":[{"pattern":"^(ok|split_history_unknown|listing_type_unread|sec_unavailable|sec_pending|listing_type_absent|listing_without_share_count|reference_split_ambiguous|listing_is_[a-z_]+)$","type":"string"},{"type":"null"}],"description":"As price_snapshot and /api/snapshot serve it (share_count.resolve_with_status): 'ok'; a PROVISIONAL reason, an input that could not be read (split_history_unknown, listing_type_unread, sec_unavailable, sec_pending), the answer then kept a minute; or why there is no count: listing_is_<type> (listing_is_warrant, listing_is_unit, listing_is_structured_product, listing_is_etn, ...: the listing is not common stock or an ADR), listing_type_absent, listing_without_share_count (its reference row carries no count of its own), reference_split_ambiguous. Without a split list read now there is no count at all (split_history_unknown). Never null when market_cap_shares is set.","title":"Market Cap Shares Status"},"shares_outstanding":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Shares (whole): the count market_cap is built on, every share class included; always equal to market_cap_shares. Null exactly when market_cap_shares is null.","title":"Shares Outstanding"},"shares_outstanding_basis":{"anyOf":[{"enum":["cover_page","reference_data","balance_sheet_period_end","latest_quarter_weighted_average_basic"],"type":"string"},{"type":"null"}],"description":"Which count shares_outstanding is; always equal to market_cap_shares_basis. Null exactly when shares_outstanding is null.","title":"Shares Outstanding Basis"},"share_class_shares_outstanding":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Shares (whole): the listed share class's own count, as the market data gives it, undated. For a multi-class issuer it is one class only (META class A 2,205,128,509 of 2,547,506,225), so it is not the count market_cap is built on. Null when the market data gives none, and for a listing share_count's gate refuses (a warrant's or a fund's count is no share class's).","title":"Share Class Shares Outstanding"},"last_price":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"USD per share: the latest price from the quote snapshot (price_as_of, price_is_stale), not market_cap_price.","title":"Last Price"},"latest_eps":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"USD per share: BASIC EPS of the newest income-statement row. When that row is the TTM window's newest quarter it shares ttm_eps_split_status: on today's share basis (divided by its own split factor when restated), null when split_history_unknown. Without a TTM block it is as filed.","title":"Latest Eps"},"ttm_eps":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"description":"USD per share: the sum of BASIC quarterly EPS over the four newest quarterly rows (ttm_eps_basis), on today's share basis (ttm_eps_split_status); a quarter without EPS is left out of the sum (ttm_quarters_with_eps). Null when ttm_eps_split_status is split_history_unknown. Absent, like every ttm_* field, when fewer than four quarterly rows were read.","title":"Ttm Eps"},"ttm_eps_basis":{"anyOf":[{"const":"basic","type":"string"},{"type":"null"}],"default":null,"description":"'basic' whenever ttm_eps is present.","title":"Ttm Eps Basis"},"ttm_eps_diluted":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"description":"USD per share: the sum of DILUTED quarterly EPS over the same four quarters, on the same share basis as ttm_eps (ttm_eps_split_status). Null unless all four carry a diluted EPS (ttm_quarters_with_eps_diluted is then 4), and null when ttm_eps_split_status is split_history_unknown; absent with the TTM block.","title":"Ttm Eps Diluted"},"ttm_eps_split_status":{"anyOf":[{"enum":["no_split_in_window","restated","split_history_unknown"],"type":"string"},{"type":"null"}],"default":null,"description":"The share basis of ttm_eps, ttm_eps_diluted and (when it is the window's newest quarter) latest_eps. Each quarter's EPS is on the share basis of the day it was FILED (a quarter re-filed after a split already carries the restated figure), so it is divided by the cumulative ratio of the splits executed after its filing date, up to today. no_split_in_window: the split list is known and no split applies to any of the four quarters; the sums are plain sums. restated: a split was applied (ttm_eps_split_ratio, ttm_eps_split_ex_dates); the sums are on today's share basis. split_history_unknown: the split read failed or timed out, or no split list was read for this listing (a note, ETN, warrant or preferred, whose statements are its issuer's); ttm_eps, ttm_eps_diluted and latest_eps are then null, since a sum that may cross an unrestated split is a wrong number. Absent with the TTM block.","title":"Ttm Eps Split Status"},"ttm_eps_split_ratio":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"description":"New shares per old share: the cumulative split ratio applied to the most-restated quarter (the one furthest from 1; NVDA's 2024-06-10 10-for-1 gives 10.0, a 1-for-10 reverse split 0.1). Non-null exactly when ttm_eps_split_status is restated.","title":"Ttm Eps Split Ratio"},"ttm_eps_split_ex_dates":{"anyOf":[{"items":{"format":"date","type":"string"},"type":"array"},{"type":"null"}],"default":null,"description":"Ex-dates (YYYY-MM-DD) of the splits applied, oldest first. Non-null exactly when ttm_eps_split_status is restated.","title":"Ttm Eps Split Ex Dates"},"ttm_quarters_with_eps":{"anyOf":[{"maximum":4,"minimum":0,"type":"integer"},{"type":"null"}],"default":null,"description":"Quarters of the four with a basic EPS.","title":"Ttm Quarters With Eps"},"ttm_quarters_with_eps_diluted":{"anyOf":[{"maximum":4,"minimum":0,"type":"integer"},{"type":"null"}],"default":null,"description":"Quarters of the four with a diluted EPS.","title":"Ttm Quarters With Eps Diluted"}},"required":["market_cap","market_cap_price","market_cap_as_of","market_cap_shares","market_cap_shares_basis","market_cap_shares_as_of","market_cap_shares_status","shares_outstanding","shares_outstanding_basis","share_class_shares_outstanding","last_price","latest_eps"],"title":"ApexEquityFundamentals","type":"object"}},"additionalProperties":true,"description":"The 200 answer of ``GET /api/v3/skills/apex_equity/{ticker}`` inside the\nstandard v3 envelope. Only ``fundamentals``' declared fields are pinned;\n``intel``, ``intel_windows``, ``flags``, ``chart``, ``charts``,\n``components`` and ``vendor_errors`` are served as the tool description says.","properties":{"ok":{"title":"Ok","type":"boolean"},"timestamp":{"title":"Timestamp","type":"string"},"skill":{"const":"apex_equity","title":"Skill","type":"string"},"ticker":{"title":"Ticker","type":"string"},"fundamentals":{"$ref":"#/$defs/ApexEquityFundamentals"}},"required":["ok","timestamp","skill","ticker","fundamentals"],"title":"ApexEquityResponse","type":"object"},"public_name":"equity_brief"},{"name":"tengu_v3_skills_trading_plan","method":"GET","path":"/api/v3/skills/trading_plan/{ticker}","group":"v3","description":"Long/short plan levels for a ticker: entry (the last completed daily close, dated plan.as_of), stop (the 20-day swing, or 1.5x ATR(14), served as plan.atr14) and 1R/2R/3R targets, plus a thesis citing supporting signals (trend, flow tilt, insider, congress) and an embedded PNG chart. FIRM serves no position size: plan.sizing's fields are null, with plan.sizing.withheld saying why. Call this when the user asks 'how would I trade X'; bias=auto picks direction from TA stance, and a balanced stance is direction 'none' with plan null and 'no_trade' saying why.","path_params":["ticker"],"query_params":[{"name":"bias","type":"string","default":"auto","enum":["auto","long","short"],"description":"auto|long|short — 'auto' picks from TA stance"},{"name":"risk_pct","type":"float","default":1.0,"min":0.1,"max":5.0,"description":"Accepted for compatibility; no size is computed from it"}],"admin":false,"display_name":"Trade plan","public_name":"trading_plan"},{"name":"tengu_v3_framework_lookup","method":"POST","path":"/api/v3/framework/lookup","group":"v3","description":"Curated decision framework for an intent (capital_allocation / verdict / comparison): methodology paragraph, decision_template (inputs_required, outputs_required, synthesis_order), and academic citations. Call it BEFORE synthesizing an allocation or verdict answer; context flags select defensive/portfolio variants.","body_schema":{"type":"object","properties":{"intent":{"type":["string","null"],"enum":["capital_allocation","verdict","comparison"]},"framework_id":{"type":["string","null"],"description":"exact framework key — wins over intent when both passed"},"context":{"additionalProperties":true,"type":["object","null"]}},"additionalProperties":false,"required":[],"description":"all fields optional — empty body returns the full framework registry listing"},"admin":false,"display_name":"Investment framework","public_name":"framework_lookup"},{"name":"tengu_v3_framework_list","method":"GET","path":"/api/v3/framework/list","group":"v3","description":"Lightweight catalogue of all registered frameworks — one row per framework with framework_id + intent + 1-line applies_when + version. Useful for discovery / debugging without parsing the full library. For the actual decision template, call tengu_v3_framework_lookup.","admin":false,"display_name":"Available frameworks","public_name":"framework_list"},{"name":"tengu_v3_briefing_daily","method":"GET","path":"/api/v3/briefing/daily","group":"v3","description":"Daily briefing for a given user_id: regime, overnight futures, earnings_today, macro_today, watchlist_signals, news_highlights, risk_exposure, top_movers. Served from a precomputed cache (~5ms) when available, else built on demand (usually a few seconds, no LLM calls). The response carries '_source': 'precomputed' or 'computed:request_time' so callers can tell which path served them. A build that does not finish within the request is a 200 with status 'preparing' and billed false (no briefing yet; it keeps building, call again after retry_after_s), and one stuck for minutes is a 503 briefing_build_stalled; neither is an empty briefing. Pass precompute_only=true ONLY when you specifically need to know whether the scheduled precompute has already run — that path returns 404 instead of building.","query_params":[{"name":"user_id","type":"string","required":true,"server_injected":true},{"name":"date","type":"string","description":"YYYY-MM-DD (default: today UTC)"},{"name":"fallback_build","type":"bool","default":true,"description":"Default true. Build synchronously when the precompute is missing."},{"name":"precompute_only","type":"bool","default":false,"description":"If true, never build synchronously; return 404 when the precompute is missing. Use for monitoring."}],"admin":false,"display_name":"Daily briefing","capability_tags":["heavy"],"public_name":"briefing_daily"},{"name":"tengu_v3_briefing_status","method":"GET","path":"/api/v3/briefing/status","group":"v3","description":"Presence check for today's briefing payload for a user/date, and whether a build is in progress on the server that answers (build_in_progress, build_state, build_elapsed_s). Call when the user asks whether the daily briefing was generated or why it looks missing.","query_params":[{"name":"user_id","type":"string","required":true,"server_injected":true},{"name":"date","type":"string"}],"admin":false,"public_name":"briefing_status"},{"name":"tengu_ml_health","method":"GET","path":"/api/ml/health","group":"ml","description":"ML pipeline freshness probe: has_predictions, has_weights_history, latest_as_of_ts, n_tickers. Call when the user asks whether the ML pipeline is healthy or why predictions look missing/stale.","admin":false,"public_name":"ml_health"},{"name":"tengu_ml_predict","method":"GET","path":"/api/ml/predict/{ticker}","group":"ml","description":"Latest ML ensemble prediction for one ticker: blended_score, conviction, decile rank, and per-voter sub-scores. Call this when the user asks 'what does the model think of X' or wants a quantitative score to weigh against fundamentals.","path_params":["ticker"],"admin":false,"public_name":"ml_predict"},{"name":"tengu_ml_top_picks","method":"GET","path":"/api/ml/top-picks","group":"ml","description":"Top-N ranked tickers from the latest ML ensemble scoring snapshot, optionally floored by min_conviction. PRIMARY tool for 'what are the model's top picks / best-ranked stocks right now'; use tengu_ml_predict for one ticker's detail.","query_params":[{"name":"n","type":"int","default":20,"min":1,"max":500,"description":"Number of picks returned (1-500)."},{"name":"min_decile","type":"int","default":10,"min":1,"max":10,"description":"Lowest decile served (1-10). The default 10 serves only the top decile."},{"name":"tier","type":"string","description":"Only picks in this liquidity tier (the `tier` field of a pick)."},{"name":"min_conviction","type":"float","default":0.0,"min":0.0,"max":1.0}],"admin":false,"public_name":"ml_top_picks"},{"name":"tengu_ml_weights","method":"GET","path":"/api/ml/weights","group":"ml","description":"ML ensemble voter weights (latest history row, broken out per market regime). These are NOMINAL weights: the blend applies voter_policy on top (a voter in disabled_voters blends with weight 0, a scaled voter with weight x its scale), so read voter_policy before treating a weight as live. Use tengu_ml_weights_history for drift over time.","admin":false,"public_name":"ml_weights"},{"name":"tengu_ml_weights_history","method":"GET","path":"/api/ml/weights/history","group":"ml","description":"Time series of ML ensemble voter weights (per regime, newest first; days=1-365, default 30). NOMINAL weights, before the voter_policy the blend applies (see tengu_ml_weights). Call this when the user asks how the model's weighting has drifted or shifted across regimes; use tengu_ml_weights for the current row.","query_params":[{"name":"days","type":"int","default":30,"description":"Days of history to return (1-365)"}],"admin":false,"public_name":"ml_weights_history"},{"name":"tengu_v3_private_markets_search","method":"GET","path":"/api/v3/private_markets/search","group":"v3","description":"Search PRIVATE companies / investors (VC/PE) / funds / people / limited partners by name (prefix, case-insensitive), ticker, or CIK — relevance-ranked so the prominent entity is #1; an exact ticker or CIK leads. Matches also-known-as, legal and former names and the homepage domain ('Nubank' finds Nu Holdings through nubank.com.br). Use this FIRST for any private-company question (e.g. 'tell me about Stripe', 'who is Sequoia') to resolve the entity id, then call the company/dossier/realtime tools. type=all searches every entity kind. detail=full returns every column per hit (for rich tables).","query_params":[{"name":"q","type":"string","required":true,"description":"Name prefix, ticker, or CIK"},{"name":"type","type":"string","default":"company","enum":["company","investor","fund","person","lp","serviceprovider","all"]},{"name":"limit","type":"int","default":10,"min":1,"max":50},{"name":"detail","type":"string","default":"lean","enum":["lean","full"],"description":"lean=key fields; full=every column per hit"},{"name":"fields","type":"string","description":"explicit comma-separated columns (overrides detail)"}],"admin":false,"public_name":"private_markets_search"},{"name":"tengu_v3_private_markets_search_suggest","method":"GET","path":"/api/v3/private_markets/search/suggest","group":"v3","description":"INSTANT (sub-100ms) private-company typeahead — prominence-ranked with the SAME ranking as search, so the famous company is never truncated; each hit carries its website/domain plus sector, last-known valuation (USD millions), ticker. Call this FIRST to resolve a name to company_id; use /search for multi-entity or detail=full.","query_params":[{"name":"q","type":"string","required":true,"description":"Company name prefix / word / ticker / CIK"},{"name":"limit","type":"int","default":8,"min":1,"max":20}],"admin":false,"public_name":"private_markets_search_suggest"},{"name":"tengu_v3_private_markets_company","method":"GET","path":"/api/v3/private_markets/company/{company_id}","group":"v3","description":"FULL private-company profile by company_id: financials (revenue/EBITDA/EBIT/net income/EV/net debt), complete financing history (round size/valuation/date/type), classification, HQ/contact, parent hierarchy, and cikcode/ticker to join public data. Money is USD millions. A financial period that has not ended is served under projected_financials, never as the TTM fields. A LISTED company carries public_transition with its ticker: use the public-equity tools for its current price and financials. An unknown id is a 404. Call it after resolving the id via search_suggest for the deep dive on one company.","path_params":["company_id"],"admin":false,"public_name":"private_markets_company"},{"name":"tengu_v3_private_markets_company_dossier","method":"GET","path":"/api/v3/private_markets/company/{company_id}/dossier","group":"v3","description":"EVERYTHING on a private company in ONE call — the complete detail-page payload: full profile (incl. financials & full financing history) + full deal history + investors + competitors + similar companies + board/team.","path_params":["company_id"],"query_params":[{"name":"deals","type":"int","default":50,"min":1,"max":200},{"name":"peers","type":"int","default":25,"min":1,"max":100},{"name":"investors","type":"int","default":100,"min":1,"max":300},{"name":"blocks","type":"string","description":"csv subset of deals,investors,competitors,similar,board (default all; 'none' = profile-only header prefetch)"},{"name":"fields","type":"string","description":"project the company profile to these columns (keeps a header-only prefetch tiny)"}],"admin":false,"capability_tags":["heavy"],"public_name":"private_markets_company_dossier"},{"name":"tengu_v3_private_markets_company_page","method":"GET","path":"/api/v3/private_markets/company/{company_id}/page","group":"v3","description":"The private-company DETAIL PAGE in ONE call, render-ready: identity + key facts + the valuation/revenue/headcount tapes + the financing-in-progress card + the team roster. Money ships as both a raw `*_musd` float and a formatted `*_display` string, every series is sorted ASCENDING for charting, and the hero valuation badge is computed server-side (never presented as an estimate unless it is one). Blocks degrade independently. Use this for a company PAGE; use /dossier for the analytical fan-out (investors/competitors/similar) and /realtime for live overlay.","path_params":["company_id"],"query_params":[{"name":"tab","type":"string","default":"valuation","enum":["valuation","revenue","headcount"],"description":"valuation|revenue|headcount — which series to return in full (others report availability)"},{"name":"deals","type":"int","default":200,"min":1,"max":500},{"name":"team","type":"int","default":60,"min":1,"max":500}],"admin":false,"display_name":"Private company page","capability_tags":["heavy"],"public_name":"private_markets_company_page"},{"name":"tengu_v3_private_markets_company_valuation","method":"GET","path":"/api/v3/private_markets/company/{company_id}/valuation","group":"v3","description":"A private valuation mark for a company: estimate, confidence band, the additive driver bridge (Round Momentum / Company Growth / Market Drift / Syndicate Quality, which sums exactly to estimate-minus-anchor) and exit probabilities that are FIXED STAGE PRIORS, not company-specific. The mark is a model estimate, not a transaction price; its confidence label is a heuristic (never above 'medium' until backtested). A listed company returns ok:false, reason company_is_public. Computed server-side from licensed private-markets deal and company data; not the data vendor's own valuation estimate or exit predictor. FAILS CLOSED: thin coverage returns ok:false with a reason rather than a fabricated mark. Every success carries as_of + model_version.","path_params":["company_id"],"query_params":[],"admin":false,"display_name":"Private valuation mark","capability_tags":["heavy"],"public_name":"private_markets_company_valuation"},{"name":"tengu_v3_private_markets_company_syndicate","method":"GET","path":"/api/v3/private_markets/company/{company_id}/syndicate","group":"v3","description":"PER-ROUND investor syndicate — who was IN each round, who LED it, and how big the check was. The two-hop join (deal x deal-investor x investor) that the flat /investors list cannot express. Rows carry dealid so they join onto /deals, plus the round's date/label/size. Role/check/holding columns are detected at read time; a field the warehouse lacks ships null (never a fabricated 'follow'), and available_fields reports what exists. Role comes from the round's lead flag; investor_status says new vs follow-on investor. Newest rounds first, each edge once.","path_params":["company_id"],"query_params":[{"name":"limit","type":"int","default":300,"min":1,"max":1000}],"admin":false,"display_name":"Round syndicate","capability_tags":["heavy"],"public_name":"private_markets_company_syndicate"},{"name":"tengu_v3_private_markets_company_realtime","method":"GET","path":"/api/v3/private_markets/company/{company_id}/realtime","group":"v3","description":"LIVE real-time overlay for a private company — the fast-moving complement to the (weekly, possibly STALE) private-markets profile, on a short TTL with per-field source provenance. ALWAYS call this for a private company to check whether it has GONE PUBLIC: it returns a `public_transition` block (new ticker, IPO date, SEC evidence) even when the snapshot still shows 'In IPO Registration'/no ticker — then pivot to the public-equity tools (price_snapshot / company_facts / sec_filings) for live data. A company already listed in the archive gets the same block (status public). Only the SEC listing check is live today; live headcount/jobs enrichment is not enabled.","path_params":["company_id"],"admin":false,"public_name":"private_markets_company_realtime"},{"name":"tengu_v3_private_markets_company_deals","method":"GET","path":"/api/v3/private_markets/company/{company_id}/deals","group":"v3","description":"Funding-round and M&A deal history for a private company (deal size, type, VC round, pre/post-money valuation), newest first. Call this when the user asks 'when did X last raise / at what valuation / who acquired it'; use /investors for who participated.","path_params":["company_id"],"query_params":[{"name":"limit","type":"int","default":50,"min":1,"max":500}],"admin":false,"public_name":"private_markets_company_deals"},{"name":"tengu_v3_private_markets_company_investors","method":"GET","path":"/api/v3/private_markets/company/{company_id}/investors","group":"v3","description":"Investor roster for a private company, resolved through the deal-investor relation; detail=full adds every investor column (AUM, dry powder, activity). Call this when the user asks 'who backed X / which VCs are on the cap table'; use /deals for the rounds themselves.","path_params":["company_id"],"query_params":[{"name":"limit","type":"int","default":100,"min":1,"max":500},{"name":"detail","type":"string","default":"lean","enum":["lean","full"],"description":"full = every investor column (AUM, dry powder, activity)"},{"name":"offset","type":"int","default":0,"min":0,"max":100000,"description":"skip this many investors — page past the `limit` cap (the relation is deterministically ordered by investorid)"}],"admin":false,"public_name":"private_markets_company_investors"},{"name":"tengu_v3_private_markets_companies","method":"GET","path":"/api/v3/private_markets/companies","group":"v3","description":"SCREEN private companies by sector, geography, financing/business status, size (total raised/valuation/employees, $MILLIONS), founding year; rows carry ticker/cikcode to join public data. PRIMARY tool for list questions like 'VC-backed fintech in Europe raised >$100M'; status=active_private excludes public/acquired/defunct (a company that has only filed to list stays in, flagged ipo_pending). Sorting by lastknownvaluation ranks on the last completed round with an actual post-money.","query_params":[{"name":"sector","type":"string"},{"name":"industry_group","type":"string"},{"name":"country","type":"string"},{"name":"region","type":"string"},{"name":"financing_status","type":"string"},{"name":"business_status","type":"string"},{"name":"q","type":"string"},{"name":"min_raised","type":"float","description":"$millions"},{"name":"max_raised","type":"float","description":"$millions"},{"name":"min_valuation","type":"float","description":"$millions"},{"name":"max_valuation","type":"float","description":"$millions"},{"name":"min_employees","type":"int"},{"name":"max_employees","type":"int"},{"name":"founded_after","type":"int"},{"name":"founded_before","type":"int"},{"name":"has_ticker","type":"bool"},{"name":"status","type":"string","default":"any","enum":["any","active_private"],"description":"active_private = currently-private OPERATING co only (excludes public/acquired-subsidiary/defunct/bankrupt; includes In IPO Registration, flagged ipo_pending). Every row also carries is_outlier (valuation > $5T sanity ceiling) so impossible figures never rank #1."},{"name":"sort","type":"string","default":"totalraised","enum":["totalraised","lastknownvaluation","employees","yearfounded","lastfinancingdate","revenue","ebitda"]},{"name":"desc","type":"bool","default":true},{"name":"limit","type":"int","default":50,"min":1,"max":500},{"name":"offset","type":"int","default":0,"min":0,"max":50000},{"name":"detail","type":"string","default":"lean","enum":["lean","full"],"description":"full = ALL ~98 columns per company (incl financials)"},{"name":"fields","type":"string","description":"explicit comma-separated columns (overrides detail)"}],"admin":false,"public_name":"private_markets_companies"},{"name":"tengu_v3_private_markets_company_comparables","method":"GET","path":"/api/v3/private_markets/company/{company_id}/comparables","group":"v3","description":"Private peer set for one company: currently-private operating companies in the same industry group (sector when it has none) and a similar size band (0.2x-5x total raised), excluding the company itself. Call this when the user asks 'who are X's private comps' or needs a peer group for valuation framing; detail=full returns every column per peer.","path_params":["company_id"],"query_params":[{"name":"limit","type":"int","default":20,"min":1,"max":100},{"name":"detail","type":"string","default":"lean","enum":["lean","full"],"description":"full = every column per peer"},{"name":"fields","type":"string","description":"explicit comma-separated columns (overrides detail)"}],"admin":false,"public_name":"private_markets_company_comparables"},{"name":"tengu_v3_private_markets_aggregates","method":"GET","path":"/api/v3/private_markets/aggregates","group":"v3","description":"Private-market landscape aggregates: company counts, total and median capital raised, median valuation, median employees. Group by sector, industry_group, region, country, vertical, founded_year, ownership, financing_status, deal_year or stage — or COMMA-SEPARATE up to 3 for a COHORT (e.g. 'deal_year,stage'), which is the grain a comparables/valuation model needs (a sector median over millions of companies is too coarse to be a comp). `min_n` drops thin buckets. Call this for market-level questions like 'which sectors raise the most' — not for single companies.","query_params":[{"name":"by","type":"string","default":"sector","description":"one dimension, or up to 3 comma-separated for a cohort (e.g. 'deal_year,stage'); dimensions: sector, industry_group, region, country, vertical, founded_year, ownership, financing_status, deal_year, stage"},{"name":"limit","type":"int","default":30,"min":1,"max":500},{"name":"min_n","type":"int","default":1,"min":1,"max":10000,"description":"drop buckets with fewer companies than this"}],"admin":false,"public_name":"private_markets_aggregates"},{"name":"tengu_v3_private_markets_news","method":"GET","path":"/api/v3/private_markets/news","group":"v3","description":"News about PRIVATE companies (venture-backed, unbacked or in IPO registration) from the private-markets news archive: funding rounds, M&A, IPO filings, partnerships, launches, leadership, legal and layoffs. One story per event with its other outlets listed, each tagged with its companies (id, sector, total raised, last completed financing). Call this for 'what is happening with private AI companies', 'latest funding news', or a private company's recent coverage (company_id). freshness.vendor_through is the newest story the archive holds; it trails real time by one to three weeks.","query_params":[{"name":"limit","type":"int","default":30,"min":1,"max":100},{"name":"sort","type":"string","default":"latest","enum":["latest","top"]},{"name":"category","type":"string","enum":["funding","m_and_a","ipo","partnership","product","people","legal","layoffs","other"]},{"name":"sector","type":"string","description":"a facets.sectors name"},{"name":"company_id","type":"string","description":"private-markets company id: 1-9 digits, a dash, 2 digits (NNNNN-NN)"},{"name":"q","type":"string","description":"headline or company name"},{"name":"cursor","type":"string","description":"next_cursor from the previous page"}],"admin":false,"display_name":"Private company news","public_name":"private_markets_news"},{"name":"tengu_v3_private_markets_investor","method":"GET","path":"/api/v3/private_markets/investor/{investor_id}","group":"v3","description":"Investor profile for one VC/PE/family office by investor_id: type, AUM, dry powder, year founded, investment focus, and median valuation/round. Call this when the user asks who an investor is or how big/active they are; use investor_relations for portfolio, funds, and co-investors.","path_params":["investor_id"],"admin":false,"public_name":"private_markets_investor"},{"name":"tengu_v3_private_markets_fund","method":"GET","path":"/api/v3/private_markets/fund/{fund_id}","group":"v3","description":"Fund profile + performance: vintage, size, category, status, and returns (IRR/DPI/TVPI/RVPI/NAV/quartile) when loaded.","path_params":["fund_id"],"admin":false,"public_name":"private_markets_fund"},{"name":"tengu_v3_private_markets_person","method":"GET","path":"/api/v3/private_markets/person/{person_id}","group":"v3","description":"Person profile (founder/exec/board member) by person_id: role, board seats, affiliated deals/funds, education, and professional-profile link. Call this when the user asks who a founder or executive is; use person_relations to walk their full career and deal history.","path_params":["person_id"],"admin":false,"public_name":"private_markets_person"},{"name":"tengu_v3_private_markets_limited_partner","method":"GET","path":"/api/v3/private_markets/limited_partner/{lp_id}","group":"v3","description":"Limited-partner profile by lp_id: LP type, AUM, total/active commitments, allocation to alternatives, and openness to first-time funds. Call this when the user asks who an LP is or how much it commits; use limited_partner_relations for its fund commitments and mandates.","path_params":["lp_id"],"admin":false,"public_name":"private_markets_limited_partner"},{"name":"tengu_v3_private_markets_deal","method":"GET","path":"/api/v3/private_markets/deal/{deal_id}","group":"v3","description":"Single deal / financing round by deal_id: deal size, type, VC round, pre/post-money valuation, and a synopsis. Call this when the user asks about a specific round ('what was the Series C?'); use deal_relations for the investors, lenders, and tranches behind it.","path_params":["deal_id"],"admin":false,"public_name":"private_markets_deal"},{"name":"tengu_v3_private_markets_service_provider","method":"GET","path":"/api/v3/private_markets/service_provider/{sp_id}","group":"v3","description":"Advisory-firm profile by sp_id — the law firm, investment bank, auditor or consultancy behind private-market deals: type, employees, parent, and count of companies serviced. Call this when the user asks who advised a deal or how big an adviser is; use service_provider_relations for its client list.","path_params":["sp_id"],"admin":false,"public_name":"private_markets_service_provider"},{"name":"tengu_v3_private_markets_service_provider_relations","method":"GET","path":"/api/v3/private_markets/service_provider/{sp_id}/relations","group":"v3","description":"Reverse adviser index for one service provider: every deal, company, investor, fund or LP the firm has advised (relation= picks the edge, limit default 50). PRIMARY tool for 'which deals did this bank run?' / 'who does this law firm work for?' — the counterparty-selection view the forward service_providers relation cannot express. A read failure returns 503 upstream_unavailable (error_code warehouse_read_failed; not billed), never an empty relation; its Retry-After (30-60 s) is when the next read will be made.","path_params":["sp_id"],"query_params":[{"name":"relation","type":"string","required":true,"enum":["deals","companies","investors","funds","limited_partners","board"]},{"name":"limit","type":"int","default":50,"min":1,"max":500}],"admin":false,"public_name":"private_markets_service_provider_relations"},{"name":"tengu_v3_private_markets_relations","method":"GET","path":"/api/v3/private_markets/relations","group":"v3","description":"Catalogue of every queryable relation per private-markets entity type — the map of the private-capital graph. Call it first when unsure which relation= value a company/investor/fund/deal/person/LP relations tool accepts before traversing.","admin":false,"public_name":"private_markets_relations"},{"name":"tengu_v3_private_markets_company_relations","method":"GET","path":"/api/v3/private_markets/company/{company_id}/relations","group":"v3","description":"Traverse a company's private-market graph one edge per call (relation=): competitors, investors, board, similar companies, affiliates, buyside targets, service providers, industries/verticals, news, financials, employee history and more. Call this when the user asks who backs, competes with, or sits on the board of a company. A read failure returns 503 upstream_unavailable (error_code warehouse_read_failed; not billed), never an empty relation; its Retry-After (30-60 s) is when the next read will be made.","path_params":["company_id"],"query_params":[{"name":"relation","type":"string","required":true,"enum":["competitors","investors","board","similar","affiliates","buyside","lead_partners","service_providers","industries","verticals","naics","sic","locations","news","financials","clinical_trials","market_analysis","stock_exchanges","entity_types","morningstar_codes","employee_history","cik_codes"]},{"name":"limit","type":"int","default":50,"min":1,"max":500}],"admin":false,"public_name":"private_markets_company_relations"},{"name":"tengu_v3_private_markets_deal_relations","method":"GET","path":"/api/v3/private_markets/deal/{deal_id}/relations","group":"v3","description":"Traverse a deal's graph one edge per call (relation=): investors, tranches, debt lenders, sellers, service providers, bonds, loans, distribution beneficiaries. Call this when the user asks who funded, lent into, or sold in a specific round after fetching the deal itself. A read failure returns 503 upstream_unavailable (error_code warehouse_read_failed; not billed), never an empty relation; its Retry-After (30-60 s) is when the next read will be made.","path_params":["deal_id"],"query_params":[{"name":"relation","type":"string","required":true,"enum":["investors","tranches","debt_lenders","sellers","service_providers","bonds","loans","distrib_beneficiaries"]},{"name":"limit","type":"int","default":50,"min":1,"max":500}],"admin":false,"public_name":"private_markets_deal_relations"},{"name":"tengu_v3_private_markets_investor_relations","method":"GET","path":"/api/v3/private_markets/investor/{investor_id}/relations","group":"v3","description":"Traverse an investor's graph one edge per call (relation=): portfolio companies, funds raised, co-investors, LPs, board, deals, news, and investment focus by industry/year. Call this when the user asks what a VC/PE firm holds, who invests alongside it, or who its LPs are. A read failure returns 503 upstream_unavailable (error_code warehouse_read_failed; not billed), never an empty relation; its Retry-After (30-60 s) is when the next read will be made.","path_params":["investor_id"],"query_params":[{"name":"relation","type":"string","required":true,"enum":["portfolio_companies","funds","co_investors","board","limited_partners","affiliates","deals","locations","news","invest_industries","invest_years","service_providers","entity_types","types"]},{"name":"limit","type":"int","default":50,"min":1,"max":500}],"admin":false,"public_name":"private_markets_investor_relations"},{"name":"tengu_v3_private_markets_fund_relations","method":"GET","path":"/api/v3/private_markets/fund/{fund_id}/relations","group":"v3","description":"Traverse a fund's graph one edge per call (relation=): investors, LP commitments, team, portfolio holdings, close history, fund family, service providers, and returns time-series. Call this when the user asks what a fund holds, who committed capital, or how it has performed. A read failure returns 503 upstream_unavailable (error_code warehouse_read_failed; not billed), never an empty relation; its Retry-After (30-60 s) is when the next read will be made.","path_params":["fund_id"],"query_params":[{"name":"relation","type":"string","required":true,"enum":["investors","lp_commitments","team","portfolio_holdings","close_history","family","service_providers","returns"]},{"name":"limit","type":"int","default":50,"min":1,"max":500}],"admin":false,"public_name":"private_markets_fund_relations"},{"name":"tengu_v3_private_markets_person_relations","method":"GET","path":"/api/v3/private_markets/person/{person_id}/relations","group":"v3","description":"Traverse a person's graph one edge per call (relation=): career positions, board seats, education, affiliated deals/funds, advisory roles. Call this when the user asks where a founder or exec worked before, what boards they sit on, or which deals they touched. A read failure returns 503 upstream_unavailable (error_code warehouse_read_failed; not billed), never an empty relation; its Retry-After (30-60 s) is when the next read will be made.","path_params":["person_id"],"query_params":[{"name":"relation","type":"string","required":true,"enum":["positions","board_seats","education","affiliated_deals","affiliated_funds","advisory"]},{"name":"limit","type":"int","default":50,"min":1,"max":500}],"admin":false,"public_name":"private_markets_person_relations"},{"name":"tengu_v3_private_markets_limited_partner_relations","method":"GET","path":"/api/v3/private_markets/limited_partner/{lp_id}/relations","group":"v3","description":"Traverse an LP's graph one edge per call (relation=): fund commitments, board, mandates, news, service providers. Call this when the user asks which funds an LP has committed to or what mandates it is running. A read failure returns 503 upstream_unavailable (error_code warehouse_read_failed; not billed), never an empty relation; its Retry-After (30-60 s) is when the next read will be made.","path_params":["lp_id"],"query_params":[{"name":"relation","type":"string","required":true,"enum":["fund_commitments","board","mandates","news","service_providers"]},{"name":"limit","type":"int","default":50,"min":1,"max":500}],"admin":false,"public_name":"private_markets_limited_partner_relations"},{"name":"tengu_v3_tape_bars","method":"GET","path":"/api/v3/tape/bars/{ticker}","group":"v3","description":"Intraday minute bars for one equity from the API's own capture (~10.5k tickers, extended hours included, each bar labelled pre / regular / post). Use when an agent needs REAL intraday price/volume history — how a ticker traded through an event, VWAP context, or a finer-grained chart than daily bars. Archive begins 2026-05-10; pass date=YYYY-MM-DD (or start+end, max 5 trading days), each a New York calendar day. 1m is the native grain; 5m/15m/1h are resampled server-side. Split-adjusted to today's share basis by default (adjust=none for as traded; `adjustment` lists the splits and the date they are recorded through). The daily-bar tool serves prices and volume as traded, so before a split adjusted minute volume is the ratio times its volume: compare with adjust=none. `limit` keeps the most recent bars and reports what it cut (truncated, n_available). Volume is the real-time capture's, not reconciled with late corrections. An empty answer carries empty_reason; a symbol neither the market-data listing nor the security master knows is a 404 unknown_ticker.","path_params":["ticker"],"query_params":[{"name":"date","type":"string","description":"trading day YYYY-MM-DD (required unless start+end given)"},{"name":"start","type":"string","description":"range start YYYY-MM-DD (with end; max 5 trading days)"},{"name":"end","type":"string","description":"range end YYYY-MM-DD (inclusive)"},{"name":"interval","type":"string","default":"1m","enum":["1m","5m","15m","1h"]},{"name":"limit","type":"int","default":5000,"min":1,"max":10000},{"name":"adjust","type":"string","default":"split","enum":["split","none"],"description":"split: split-adjusted to today's share basis; none: as traded"}],"param_constraints":[{"at_least_one_of":["date","start"]}],"admin":false,"display_name":"Intraday bars","capability_tags":["heavy"],"public_name":"tape_bars"},{"name":"tengu_v3_tape_index_bars","method":"GET","path":"/api/v3/tape/index_bars/{index}","group":"v3","description":"Intraday minute bars for the major index tapes — SPX, NDX, DJI, RUT, VIX — from the API's own indices capture. Use for intraday market/vol context around an event (how did SPX and VIX move through the FOMC statement?) or as the benchmark leg next to tengu_v3_tape_bars. Archive begins 2026-05-14; one day or max 5 trading days per call, each a New York calendar day. Index levels carry no traded volume, so volume, vwap and n_ticks are null; `coverage` counts regular-session minutes the capture is missing.","path_params":["index"],"query_params":[{"name":"date","type":"string","description":"trading day YYYY-MM-DD (required unless start+end given)"},{"name":"start","type":"string"},{"name":"end","type":"string"},{"name":"interval","type":"string","default":"1m","enum":["1m","5m","15m","1h"]},{"name":"limit","type":"int","default":5000,"min":1,"max":10000}],"param_constraints":[{"at_least_one_of":["date","start"]}],"admin":false,"display_name":"Index intraday bars","capability_tags":["heavy"],"public_name":"tape_index_bars"},{"name":"tengu_v3_tape_options","method":"GET","path":"/api/v3/tape/options/{ticker}","group":"v3","description":"Raw options trade prints for one underlying on one trading day from the API's own capture — per-print premium (notional_usd), strike, expiry, block/sweep flags, sorted largest premium first. For the tape behind a flow signal: whale prints, sweeps, what struck when. Archive begins 2026-05-11; date is mandatory. Source by UTC day, named per row (provenance): live capture from 2026-10-01; vendor trade history (rest_backfill) from 2026-07-30; the original capture before that. A day still being backfilled is a 503 archive_gap_pending (Retry-After), not an empty tape. Before 2026-07-30 only $25,000+ premiums were kept (is_sweep null); from then, names trading over $10M a day plus major ETFs and index options (another name's empty day is not quiet). rows_total = the day's print count for the filters; truncated = the day holds more prints than returned; pass next_cursor as cursor for the next-largest page (null on the last). Pages never repeat or skip a print.","path_params":["ticker"],"query_params":[{"name":"date","type":"string","required":true,"description":"trading day YYYY-MM-DD"},{"name":"min_premium","type":"float","min":0,"description":"only prints with notional_usd >= this (e.g. 25000 for whales)"},{"name":"side","type":"string","enum":["C","P"],"description":"filter one side (also accepts call/put)"},{"name":"limit","type":"int","default":1000,"min":1,"max":5000},{"name":"cursor","type":"string","description":"next_cursor from the previous page of the same ticker, date, side and min_premium"}],"admin":false,"display_name":"Options tape","capability_tags":["heavy"],"public_name":"tape_options"},{"name":"tengu_v3_tape_futures","method":"GET","path":"/api/v3/tape/futures/{root}","group":"v3","description":"Raw CME futures trade prints for one root (NG, CL, ES...) and one day, from the API's own capture: per-print price, size, notional, block flag across contract months. For futures flow: energy, rolls, block prints. date mandatory; archive from 2026-05-13. Source by UTC day, named per row (provenance): live capture from 2026-10-01; vendor trade history (rest_backfill) from 2026-07-30; the original capture before that. A day still being backfilled is a 503 archive_gap_pending (Retry-After), not an empty tape. From 2026-07-30 every outright of 28 CME, CBOT, NYMEX and COMEX products; before, mostly CME energy (NG heavy): an empty day then = root not captured. A day can hold more prints than limit: rows are its most recent (window most_recent, served oldest first); rows_total = the day's print count; truncated = the day holds more prints than returned; pass next_cursor as cursor for the next-older page (null on the last). Pages never repeat or skip a print.","path_params":["root"],"query_params":[{"name":"date","type":"string","required":true,"description":"trading day YYYY-MM-DD"},{"name":"limit","type":"int","default":1000,"min":1,"max":5000},{"name":"cursor","type":"string","description":"next_cursor from the previous page of the same root and date"},{"name":"before","type":"string","description":"ISO-8601 instant (no offset = UTC): the most recent prints traded strictly before it; coarse, page with cursor"}],"admin":false,"display_name":"Futures tape","capability_tags":["heavy"],"public_name":"tape_futures"},{"name":"tengu_v3_tape_futures_curve","method":"GET","path":"/api/v3/tape/futures_curve/{root}","group":"v3","description":"Futures term structure for one CME root (27 roots incl. ES, NQ, CL, NG, GC, ZN) from the API's daily chain snapshots (~22:00 UTC weekdays): the front listed months that traded in the prior six days (up to six per root, not the whole listed curve), each with last price, bid/ask, settlement, previous settlement, settle-to-settle change, volume, expiry and days-to-expiry. No open interest (always null) and no session OHLC. session_settled=false: no settled session that day, last_price is an earlier session's. Snapshots from before the 2026-09-24 capture correction, until restated, withhold settlement, change, volume and expiry (pre_fix_capture=true). Call it for curve shape (contango/backwardation) or roll; omit date for latest, snapshots begin 2026-05-18. A day after the newest snapshot is a 503 naming it, not an empty curve.","path_params":["root"],"query_params":[{"name":"date","type":"string","description":"snapshot day YYYY-MM-DD — omit for latest"},{"name":"limit","type":"int","default":120,"min":1,"max":500}],"admin":false,"display_name":"Futures curve","capability_tags":["heavy"],"public_name":"tape_futures_curve"},{"name":"tengu_v3_tape_futures_contracts","method":"GET","path":"/api/v3/tape/futures_contracts/{root}","group":"v3","description":"Live list of the tradeable outright futures contracts for one product root (ES, NQ, CL, GC, ZN, 6E, SR3...), front month first, each with its true delivery month, first/last trade dates, settlement date and days to expiry. Call it to turn a root into the exact contract ticker before asking futures_live for prices, or to see the listed months. One-digit year codes are resolved: ESH0 is March 2030 here, never March 2020.","path_params":["root"],"query_params":[{"name":"limit","type":"int","default":24,"min":1,"max":200,"description":"max contracts returned, front month first"}],"admin":false,"display_name":"Futures contracts","public_name":"tape_futures_contracts"},{"name":"tengu_v3_tape_futures_live","method":"GET","path":"/api/v3/tape/futures_live/{symbol}","group":"v3","description":"Live market data for ONE futures contract: pass a contract (ESZ6, CLX6; the archive's CLX26 spelling is accepted) or a root (ES, CL) for its front month. Snapshot (last trade, bid/ask, dated session OHLC, previous settlement and change against it), most recent trades and quotes (newest first) and daily session bars with settlement and dollar_volume in USD (contract multiplier applied), all UTC-stamped. Call it for 'where is ES trading now', intraday context, or a contract month's recent daily path. Data that cannot be attributed to the contract (its ticker also named one from another decade) is withheld and said so.","path_params":["symbol"],"query_params":[{"name":"include","type":"string","default":"snapshot,trades,quotes,daily","description":"comma list of snapshot, trades, quotes, daily"},{"name":"limit","type":"int","default":50,"min":1,"max":1000,"description":"max trades AND max quotes (each), newest first"},{"name":"days","type":"int","default":30,"min":1,"max":370,"description":"calendar days of daily session bars"}],"admin":false,"display_name":"Live futures","public_name":"tape_futures_live"},{"name":"tengu_v3_tape_microstructure","method":"GET","path":"/api/v3/tape/microstructure/{ticker}","group":"v3","description":"Microstructure windows per ticker from the API's live tape: rolling 60 s vwap, trade count/avg size, block count/vol, buy/sell imbalance, large-trade premium. Each row is a rolling 60 s window sampled about every 75-90 s, with gaps; `coverage` states the spacing and gaps, and the latest windows carry the producer's integrity state. Call it to separate smart-money accumulation from retail moves. Active-set coverage (~few hundred names/session; empty = uncaptured); omit date for latest, capture from 2026-05-13.","path_params":["ticker"],"query_params":[{"name":"date","type":"string","description":"trading day YYYY-MM-DD — omit for latest"},{"name":"limit","type":"int","default":500,"min":1,"max":5000}],"admin":false,"display_name":"Microstructure windows","capability_tags":["heavy"],"public_name":"tape_microstructure"},{"name":"tengu_v3_intel_options_flow_history","method":"GET","path":"/api/v3/intel/options_flow_history/{ticker}","group":"v3","description":"Historical options-flow aggregates for one ticker — the ~60s warehouse capture behind the live /intel/options_flow tool. Call when you need how flow EVOLVED (e.g. 'was NVDA flow bullish before the earnings pop?') rather than the current snapshot. Each row aggregates, at one ~60s poll, this ticker's alerts of $50,000+ premium among the feed's latest 200 alerts across all tickers: as_of_ts, n_alerts, premium_total (their premium with sweeps weighted 1.5x, so not dollars traded: the unweighted premium lies between premium_total / 1.5 and premium_total) and polarity (-1..1 weighted net bullish share, shrunk by min(1, n_alerts / 5), so one fully bullish alert scores 0.2). The units block states each. Summary: per-snapshot peak/avg weighted premium, avg polarity, bullish/bearish snapshot counts; never sum premium_total across rows (polls overlap). REQUIRES date OR start(+end), max 7 days per request (422 otherwise); warehouse coverage begins 2026-05-10. 5-min cache.","path_params":["ticker"],"query_params":[{"name":"date","type":"string","description":"single UTC day (YYYY-MM-DD)"},{"name":"start","type":"string","description":"window start (UTC day, inclusive)"},{"name":"end","type":"string","description":"window end (inclusive; defaults to start+6d capped at today; max 7-day window)"},{"name":"min_premium","type":"number","min":0,"description":"only snapshots whose sweep-weighted premium_total is >= this"},{"name":"side","type":"string","enum":["bullish","bearish"],"description":"polarity filter: bullish (>0) or bearish (<0) net flow"},{"name":"limit","type":"int","default":1000,"min":1,"max":5000}],"param_constraints":[{"at_least_one_of":["date","start"]}],"admin":false,"display_name":"Options flow history","capability_tags":["heavy"],"public_name":"intel_options_flow_history"},{"name":"tengu_v3_intel_iv_analytics","method":"GET","path":"/api/v3/intel/iv_analytics/{ticker}","group":"v3","description":"Implied-volatility analytics from the end-of-day archive in one call; as_of is the latest completed session (during market hours, the prior session), not intraday. IV RANK (implied volatility as a fraction and its 1-year IV rank on a 0-100 scale: 0 = the 1-year low, 100 = the 1-year high; the standard 'is vol cheap or rich' gauge, with a plain-language verdict), SKEW (the feed's 25-delta risk reversal per expiry, an IV difference: put-vs-call demand / crash premium; its sign is not documented, and positive values have come while puts were priced above calls, so do not read positive as call demand), and TERM STRUCTURE (IV per expiry + implied move in USD and implied_move_pct in percent of the price; the move measures about 0.68 x close x IV x sqrt(days/365), below a one-standard-deviation move and below the at-the-money straddle), labelled backwardation vs contango from the expiries nearest 30 and 90 DTE, named in shape_tenors. Expiries settling on the as_of session are left out. The units block gives every unit. Use for 'should I buy or sell premium on X', earnings-vol setups, and hedging cost. Omit date for the latest session; a date that is not a session is a 422 naming the prior one. A block that cannot be read refuses the call (503). NOT the same as /intel/vol_surface, which serves the lagged academic surface.","path_params":["ticker"],"query_params":[{"name":"date","type":"string","description":"session date YYYY-MM-DD; omit for the latest completed session"},{"name":"limit","type":"int","default":60,"min":1,"max":400}],"capability_tags":["heavy"],"admin":false,"public_name":"intel_iv_analytics"},{"name":"tengu_v3_intel_gex_history","method":"GET","path":"/api/v3/intel/gex_history/{ticker}","group":"v3","description":"Historical dealer gamma-exposure (GEX) for one ticker — daily per-strike snapshots behind the live /intel/gex tool. Call for 'how did dealer positioning shift into OPEX / earnings?'. GEX is in SHARES of underlying per $1 move (gamma x OI x 100; calls positive, puts negative; net_gex = call + put), not dollars, and scales with the square of a split ratio: a window across a split is flagged in warnings, and the units block says how to convert. Default returns ONE ROW PER TRADING DAY (call/put/net GEX totals, strike count, max-gamma strike); pass per_strike=true for the full strike ladder (gamma/charm/vanna + call/put GEX per strike). The archive does not hold every ticker on every session: coverage gives sessions_expected, sessions_served and missing_dates for the window. REQUIRES date OR start(+end), max 30 days per request (422 otherwise); coverage begins 2026-05-10. 10-min cache.","path_params":["ticker"],"query_params":[{"name":"date","type":"string","description":"single trading day (YYYY-MM-DD)"},{"name":"start","type":"string","description":"window start (inclusive)"},{"name":"end","type":"string","description":"window end (inclusive; defaults to start+29d capped at today; max 30-day window)"},{"name":"per_strike","type":"bool","default":false,"description":"true = raw per-strike rows; false (default) = one aggregated row per day"},{"name":"limit","type":"int","default":10000,"min":1,"max":50000}],"param_constraints":[{"at_least_one_of":["date","start"]}],"admin":false,"display_name":"Gamma exposure history","capability_tags":["heavy"],"public_name":"intel_gex_history"},{"name":"tengu_v3_intel_market_tide","method":"GET","path":"/api/v3/intel/market_tide","group":"v3","description":"Whole-market options net-premium tide for one session, one tick every 5 minutes: net call premium and net put premium (USD, premium traded at the ask minus at the bid) and net volume (contracts), each CUMULATIVE since the session open as of the tick's UTC time, so the latest tick is the session so far; never add ticks together. Omit date for the latest session, read live from the options-flow feed (60 s cache); a past session comes from the tide archive, which holds sessions from 2026-06-05, each captured after its close. Call it for whether options money leaned to calls or puts through a session. A date that is not a session is a 422; a past session the archive missed says so (status not_in_archive). Pair with sector_tide and etf_tide.","query_params":[{"name":"date","type":"string","description":"session YYYY-MM-DD; omit for the latest"}],"admin":false,"display_name":"Market options tide","public_name":"intel_market_tide"},{"name":"tengu_v3_intel_sector_tide","method":"GET","path":"/api/v3/intel/sector_tide/{sector}","group":"v3","description":"One sector's options net-premium tide for one session, per tick (archived sessions: one per minute) with each tick's UTC time: net call and net put premium (USD, at the ask minus at the bid) and net volume (contracts), served as the feed publishes them per tick; whether a tick is that interval's flow or a running total is not stated, so never add ticks. Sectors: technology, healthcare, energy, consumer_cyclical, consumer_defensive, communication_services, industrials, utilities, real_estate, basic_materials (anything else is a 422 with the list). Omit date for the latest session, read live; a past session comes from the tide archive (from 2026-06-05). Call it to see which sectors options buyers leaned into.","path_params":["sector"],"query_params":[{"name":"date","type":"string","description":"session YYYY-MM-DD; omit for the latest"}],"admin":false,"display_name":"Sector options tide","public_name":"intel_sector_tide"},{"name":"tengu_v3_intel_etf_tide","method":"GET","path":"/api/v3/intel/etf_tide/{etf}","group":"v3","description":"One ETF's options net-premium tide for one session, per tick (archived sessions: one per minute) with its UTC time: net call and net put premium (USD, at the ask minus at the bid), net volume (contracts) and the ETF's price (USD), served as the feed publishes them per tick; never add ticks. Any ETF for the latest session, read live; past sessions from the tide archive for SPY, QQQ and IWM (from 2026-06-05), and a past date for another ETF is a 422 naming those three. Call it for index-ETF options positioning through a session.","path_params":["etf"],"query_params":[{"name":"date","type":"string","description":"session YYYY-MM-DD (SPY, QQQ, IWM only); omit for the latest"}],"admin":false,"display_name":"ETF options tide","public_name":"intel_etf_tide"},{"name":"tengu_v3_intel_net_premium","method":"GET","path":"/api/v3/intel/net_premium/{ticker}","group":"v3","description":"One ticker's options net-premium ticks for one session, one row per minute carrying that minute's flow (tape_time, UTC): net call and net put premium (USD, premium traded at the ask minus at the bid), net call and put volume and total call/put volume by side of the book (contracts), and the feed's net delta (read for sign and relative size). Omit date for the latest session (60 s cache); a past session inside the feed's history window (about 730 sessions) is cached for hours, and an older one is a 422. An unknown symbol is a 404. Call it for when in a session options buyers leaned to calls or puts on a name.","path_params":["ticker"],"query_params":[{"name":"date","type":"string","description":"session YYYY-MM-DD; omit for the latest"}],"admin":false,"display_name":"Options net premium (intraday)","public_name":"intel_net_premium"},{"name":"tengu_v3_intel_gex_strikes","method":"GET","path":"/api/v3/intel/gex_strikes/{ticker}","group":"v3","description":"Dealer greek exposure per strike for one ticker, current session, all expiries summed at each strike: call_gex / put_gex / net_gex in SHARES of underlying per $1 move (gamma x OI x 100; calls positive, puts negative), call_delta / put_delta in shares, and charm and vanna per leg and net. totals gives the ladder's call, put and net GEX; gamma_usd_per_1pct_move gives them in dollars per 1% move at the stated spot (null with a reason when the spot is not from the exposure's session). The units block states each, as on tengu_v3_intel_gex and tengu_v3_intel_gex_history. Narrow with min_strike / max_strike. Earlier sessions: gex_history with per_strike=true. An unknown symbol is a 404.","path_params":["ticker"],"query_params":[{"name":"min_strike","type":"number","min":0},{"name":"max_strike","type":"number","min":0}],"admin":false,"display_name":"Gamma exposure by strike","public_name":"intel_gex_strikes"},{"name":"tengu_v3_intel_options_volume_history","method":"GET","path":"/api/v3/intel/options_volume_history/{ticker}","group":"v3","description":"Daily options volume history for one ticker from the options-volume archive (one row per session, newest first; each ticker's depth is its own, about two years for most, served as history_from, and a window before it answers status before_coverage): call and put volume (contracts, also split by side of the book), call and put open interest (contracts), call and put premium and net premium (USD), the feed's bullish/bearish premium split (USD) and its 3/7/30-session average volumes, with put_call_ratio (null with a reason when there were no calls). Each session is captured once after its close; as_of is the newest session served. REQUIRES date or start(+end), max 1830 days. An unknown symbol is a 404.","path_params":["ticker"],"query_params":[{"name":"date","type":"string","description":"one session YYYY-MM-DD"},{"name":"start","type":"string","description":"window start"},{"name":"end","type":"string","description":"window end (inclusive; max 1830 days)"},{"name":"limit","type":"int","default":500,"min":1,"max":2000}],"param_constraints":[{"at_least_one_of":["date","start"]}],"capability_tags":["heavy"],"admin":false,"display_name":"Options volume history","public_name":"intel_options_volume_history"},{"name":"tengu_v3_intel_darkpool_history","method":"GET","path":"/api/v3/intel/darkpool_history/{ticker}","group":"v3","description":"Historical dark-pool (off-exchange) prints for one ticker — the per-print warehouse capture behind the live /intel/darkpool tool. Call to find WHEN large blocks hit and whether they printed at bid/mid/ask. Each row is an individual execution: executed_at, price, size, premium (USD), market center + the NBBO at print time, and session (regular, pre_market, after_hours, or closed on a day with no NYSE session; from executed_at in New York time); newest first, plus total premium/size summary. For active names the capture holds a subset of each day's prints (capture_note), so totals are over captured prints only. REQUIRES date OR start(+end), max 7 days per request (422 otherwise); coverage begins 2026-05-10. 5-min cache.","path_params":["ticker"],"query_params":[{"name":"date","type":"string","description":"single UTC day (YYYY-MM-DD)"},{"name":"start","type":"string","description":"window start (inclusive)"},{"name":"end","type":"string","description":"window end (inclusive; defaults to start+6d capped at today; max 7-day window)"},{"name":"min_premium","type":"number","min":0,"description":"only prints with premium >= this many USD (size x price)"},{"name":"limit","type":"int","default":1000,"min":1,"max":5000}],"param_constraints":[{"at_least_one_of":["date","start"]}],"admin":false,"display_name":"Dark pool history","capability_tags":["heavy"],"public_name":"intel_darkpool_history"},{"name":"tengu_v3_intel_borrow_cost_history","method":"GET","path":"/api/v3/intel/borrow_cost_history/{ticker}","group":"v3","description":"Daily securities-lending borrow-cost HISTORY for one ticker from the licensed-research warehouse (default: last 90 days of coverage; max 365-day window). Primary source securities-finance Securities Finance (~50M rows 2010->latest licensed-research drop): annualized fee_pct / rebate_pct, utilization_pct and on-loan/lendable share quantities — the institutional squeeze-watch series (rising fee + utilization = tightening borrow). Falls back to implied-vol option-implied borrow (shortest tenor per day) when securities-finance lacks the name. licensed-research refreshes on a lag — check as_of before treating the newest row as current; use /intel/borrow_cost for the live snapshot. 1h cache.","path_params":["ticker"],"query_params":[{"name":"start","type":"string","description":"series start (inclusive; default end-90d)"},{"name":"end","type":"string","description":"series end (inclusive; default today; max 365-day window)"},{"name":"limit","type":"int","default":365,"min":1,"max":2000}],"admin":false,"display_name":"Borrow cost history","public_name":"intel_borrow_cost_history"},{"name":"tengu_v3_transcripts_list","method":"GET","path":"/api/v3/transcripts/{ticker}","group":"v3","description":"List a company's earnings calls and investor-event transcripts (1.75M calls), newest first — call this FIRST to get the ``event_id`` you pass to the full-text route. One row per call (versions collapsed to the best copy: Proofed > Edited > Spellchecked) with date, title and event type. Full text is held from 2020 on, recent calls included; older calls, and any call whose text is not held, are metadata-only.","path_params":["ticker"],"query_params":[{"name":"since","type":"string","description":"only calls on/after this date (YYYY-MM-DD)"},{"name":"limit","type":"int","default":25,"min":1,"max":100}],"admin":false,"display_name":"Earnings call list","public_name":"transcripts_list"},{"name":"tengu_v3_transcript_text","method":"GET","path":"/api/v3/transcripts/{ticker}/{event_id}","group":"v3","description":"Full earnings-call transcript as ordered speaker turns — use when the user wants what management or analysts actually SAID on a call. ``event_id`` comes from /api/v3/transcripts/{ticker} or /transcripts/search. Each turn carries speaker name + role (executive/analyst/operator) and section (presentation vs qa). ~2 MB text cap (``truncated: true`` when hit — refetch with components= to slice). Text from 2020 on; a call whose text is not held answers 404 transcript_text_not_found. A call is served only under a ticker of the company (issuer) it belongs to: another company's event_id answers 404 event_not_for_ticker naming the owner, and a symbol that maps to no company answers 404 ticker_not_resolved.","path_params":["ticker","event_id"],"query_params":[{"name":"components","type":"string","default":"all","enum":["all","presentation","qa"],"description":"presentation = prepared remarks only, qa = analyst Q&A only"},{"name":"max_turns","type":"int","default":800,"min":1,"max":1500}],"admin":false,"display_name":"Earnings call transcript","public_name":"transcript_text"},{"name":"tengu_v3_transcripts_search","method":"GET","path":"/api/v3/transcripts/search","group":"v3","description":"Search earnings-call transcripts. scope=headlines (default) searches call titles across ALL companies; scope=text searches the spoken words inside one company's transcripts (ticker REQUIRED) and returns per-call hit counts + a snippet. Use when the user asks 'which calls mention X' — then fetch the full text with the returned event_id. Headline results name each call's company. Text results are one per call (best copy), each with its date and title; hits counts the speaker turns that mention the term and the snippet is cut around the first match.","path_params":[],"query_params":[{"name":"q","type":"string","required":true,"description":"search term, min 3 chars"},{"name":"ticker","type":"string","description":"restrict to one company (required for scope=text)"},{"name":"since","type":"string","description":"only calls on/after this date (YYYY-MM-DD)"},{"name":"scope","type":"string","default":"headlines","enum":["headlines","text"]},{"name":"limit","type":"int","default":20,"min":1,"max":50}],"admin":false,"display_name":"Transcript search","public_name":"transcripts_search"},{"name":"tengu_v3_events","method":"GET","path":"/api/v3/events/{ticker}","group":"v3","description":"Company corporate-event history from a licensed events feed (41.9M events, 1990-2026): M&A, guidance changes, buybacks, exec changes, activism, offerings, index adds/drops + 100 more types, newest-first dated headlines + summaries. PRIMARY tool for 'what happened at COMPANY'; filter type= (see /api/v3/events/types), since/until. One event per key development (the vendor's current version), with every type (types[]) and every role the company plays (roles[]); limit and n count events. With type=, the top-level type is one you asked for. include_closed=true also returns developments the vendor closed, flagged vendor_status 'closed' with closed_at (the vendor's timestamp, no zone stated). data_through is the archive's newest entry day (is_stale grades it); nothing after it is held yet. An empty answer's empty_reason says which it is: window_after_coverage / none_through_data_through (not covered yet), none_in_window (none exist), coverage_unknown.","path_params":["ticker"],"query_params":[{"name":"type","type":"string","description":"comma-separated event-type slugs or numeric ids (see /api/v3/events/types), e.g. 'earnings_calls,m_and_a_transaction_announcements' or '48,80'"},{"name":"since","type":"string","description":"only events on/after this date (YYYY-MM-DD)"},{"name":"until","type":"string","description":"only events on/before this date (YYYY-MM-DD)"},{"name":"limit","type":"int","default":100,"min":1,"max":500},{"name":"include_closed","type":"bool","default":false,"description":"also return key developments the vendor has closed (no current version), flagged vendor_status 'closed' with closed_at"}],"admin":false,"display_name":"Corporate events","public_name":"corporate_events"},{"name":"tengu_v3_events_types","method":"GET","path":"/api/v3/events/types","group":"v3","description":"Legend of the 105 licensed institutional KeyDev corporate-event types: id, human label, and the slug accepted by the type= filter of /api/v3/events/{ticker}. Static — call once to discover valid event-type filters.","path_params":[],"query_params":[],"admin":false,"display_name":"Event types","public_name":"corporate_event_types"},{"name":"tengu_v3_credit","method":"GET","path":"/api/v3/credit/{ticker}","group":"v3","description":"One-call credit snapshot for a company — call FIRST for any 'how risky is this company's debt?' question: latest securities-finance 5Y CDS spread (bps) with ~90-quote trend + market-implied default probability, the current S&P rating of the issuer's OUTSTANDING rated issues (issue grain: withdrawn and matured issues excluded, rating_basis says how; null when no outstanding issue is rated) with the last upgrade/downgrade (last_action; a new issue's first rating is newest_rating_action), a recent FINRA TRACE bond yield/volume summary, and the syndicated-loan-facility count (all-time, plus the facilities still active summed per currency, withheld when the record is historical; data_through dates it). default_prob is the 5-year cumulative risk-neutral probability; the CDS block carries age_days against the archive's end. Blocks degrade independently (a missing dataset returns an error field in its block; a block not answered inside the time budget is skipped_budget); when no block answers, the call is a 503 credit_snapshot_timeout. A symbol neither the security master nor the market-data listing knows is a 404 unknown_ticker. Drill down with the credit bonds/cds/ratings/loans tools.","path_params":["ticker"],"query_params":[],"admin":false,"display_name":"Credit snapshot","capability_tags":["heavy"],"public_name":"credit_snapshot"},{"name":"tengu_v3_credit_bonds","method":"GET","path":"/api/v3/credit/bonds/{ticker}","group":"v3","description":"FINRA TRACE corporate-bond trade prints for one issuer — individual OTC trades (price, yield, volume, buy/sell side) showing where the company's bonds ACTUALLY trade (realised credit spreads, not quotes). Matched by the FINRA bond-symbol prefix of the equity ticker; window spans at most 90 days (422 beyond). TRACE on licensed-research lags realtime by months — when the default recent window is empty the response includes latest_available; page backwards from it.","path_params":["ticker"],"query_params":[{"name":"start","type":"string","description":"ISO date; window start (default end - 30 days)"},{"name":"end","type":"string","description":"ISO date; window end (default today); start..end may span at most 90 days"},{"name":"limit","type":"int","default":1000,"min":1,"max":5000}],"admin":false,"display_name":"Bond trades","capability_tags":["heavy"],"public_name":"credit_bonds"},{"name":"tengu_v3_origin_short_activity","method":"GET","path":"/api/v3/origin/short_activity/{ticker}","group":"v3","description":"How shorted is this name, from the tape itself: the DAILY consolidated short-volume prints (short ratio per session, full-market coverage) joined with the settled SHORT INTEREST published twice monthly (position, days-to-cover). Call it for squeeze setups, crowded shorts, or to check whether daily shorting is rising while settled interest lags. The two measures are a FLOW and a STOCK and can diverge — never treat them as the same number. Share volume is FRACTIONAL by design (retail fractional trading), so sub-1-share values are genuine.","path_params":["ticker"],"query_params":[{"name":"days","type":"int","default":30,"min":5,"max":180}],"admin":false,"capability_tags":["heavy"],"public_name":"origin_short_activity"},{"name":"tengu_v3_origin_whale_holdings","method":"GET","path":"/api/v3/origin/whale_holdings","group":"v3","description":"What the tracked managers own, as filed on Form 13F: each manager's latest filing, when it is for the quarter now due or the one before, with value in USD, share/principal count and portfolio weight (a 0-1 fraction of the filing's total value), filterable by manager or issuer. period_ending is on every position; manager_periods grades each manager and lagging_note names those a quarter behind. Older filings are listed in managers_with_old_filings, not mixed in (reason 'filer_cik_changed' when the filings held are a retired CIK's and the manager files under a new one); a manager= query serves that manager's latest filing, graded by is_stale. Call it for whale positioning and conviction sizing. 13F is filed within 45 days of quarter end and covers LONG US equity only — it is a lagged, partial view of a book, never a live one.","query_params":[{"name":"manager","type":"string"},{"name":"ticker","type":"string"},{"name":"limit","type":"int","default":50,"min":1,"max":500}],"admin":false,"public_name":"origin_whale_holdings"},{"name":"tengu_v3_origin_insider_flow","method":"GET","path":"/api/v3/origin/insider_flow/{ticker}","group":"v3","description":"Insider transactions straight from the Form 4 filings: owner, title, transaction code, direction, shares, price and shares held after. Call it for insider conviction around events. Transaction codes matter — 'P'/'S' are open-market buys/sells while 'M' is an option exercise and 'A' an award; treating them alike overstates conviction. Coverage is a tracked issuer set, not the whole market: an empty answer says which it is (coverage_status not_covered, for an issuer outside the set, points to tengu_v3_intel_insider_flow; no_filings_in_window names the dates held).","path_params":["ticker"],"query_params":[{"name":"days","type":"int","default":90,"min":7,"max":365},{"name":"limit","type":"int","default":100,"min":1,"max":500}],"admin":false,"public_name":"origin_insider_flow"},{"name":"tengu_v3_origin_macro_pulse","method":"GET","path":"/api/v3/origin/macro_pulse","group":"v3","description":"One call for the cross-asset state of the world from the issuing authorities: volatility futures TERM STRUCTURE (contango vs backwardation — the stress regime flag), the composite LEADING INDICATOR by country, official-sector positioning (primary-dealer net positions by maturity bucket in USD millions and the Fed's Treasury holdings at par, each with its change from the prior report), recent TREASURY AUCTIONS, and physical-trade throughput at the maritime chokepoints. Call it to frame regime before a single-name view. Each block reports its own availability; the leading indicator publishes with a ~2-month reference lag BY CONSTRUCTION — that is not staleness.","query_params":[],"admin":false,"capability_tags":["heavy"],"public_name":"origin_macro_pulse"},{"name":"tengu_v3_origin_ipo_pipeline","method":"GET","path":"/api/v3/origin/ipo_pipeline","group":"v3","description":"What is going public: deals that are priced, upcoming or newly filed, with offer size, share count, exchange and dates. Call it for new-issue supply, going-public timing, or to corroborate a private-company transition signal. This is a SECOND, independent view of going-public activity — corroborate it against the filing index rather than treating either source as complete alone. Each deal is served under its current state only (a priced deal is never 'upcoming'; an upcoming deal past its expected pricing date is listed in expected_date_passed); as_of, data_through and is_stale date each list.","query_params":[{"name":"status","type":"string","default":"upcoming","enum":["priced","upcoming","filed"]},{"name":"limit","type":"int","default":50,"min":1,"max":200}],"admin":false,"public_name":"origin_ipo_pipeline"},{"name":"tengu_v3_macro_history_dealer_positioning","method":"GET","path":"/api/v3/macro_history/dealer_positioning","group":"v3","description":"Weekly primary-dealer NET positions in Treasury bills, coupons by maturity bucket, TIPS, floating-rate notes and agency debt (FR 2004), each week as of its Wednesday (as_of_date), in millions of USD (long minus short; negative = net short). History from 2013. The New York Fed publishes a week about eight days later; freshness.as_of is the newest week held. Call it for dealer balance-sheet capacity, duration positioning or how dealers absorbed supply. Filter with series (comma list, e.g. bills,coupons_7y_to_11y); an unknown series is a 422 listing the accepted ones.","query_params":[{"name":"series","type":"string","description":"comma list of series keys (default all 15)"},{"name":"start","type":"string","description":"YYYY-MM-DD (default end - 2 years)"},{"name":"end","type":"string","description":"YYYY-MM-DD (default today); at most 20 years per call"}],"admin":false,"display_name":"Dealer positioning history","public_name":"macro_history_dealer_positioning"},{"name":"tengu_v3_macro_history_fed_holdings","method":"GET","path":"/api/v3/macro_history/fed_holdings","group":"v3","description":"The Federal Reserve's Treasury holdings (System Open Market Account), weekly as of each Wednesday: total par in USD and par by type (bills, notes and bonds, TIPS, FRNs) with security counts; or, with cusip, one security's weekly par, change on the week (USD; 0 when unchanged), coupon (percent) and share of the issue outstanding (percent). Published the next day. The weekly history is held from late July 2026; missing_weeks lists Wednesdays with nothing held. Agency MBS are not included. Call it to track quantitative tightening or the Fed's share of an issue.","query_params":[{"name":"start","type":"string","description":"YYYY-MM-DD (default end - 26 weeks)"},{"name":"end","type":"string","description":"YYYY-MM-DD (default today); at most 10 years per call"},{"name":"cusip","type":"string","description":"9-character CUSIP for one security's history"}],"admin":false,"display_name":"Fed Treasury holdings","public_name":"macro_history_fed_holdings"},{"name":"tengu_v3_macro_history_treasury_auctions","method":"GET","path":"/api/v3/macro_history/treasury_auctions","group":"v3","description":"U.S. Treasury auction results: CUSIP, term, auction/issue/maturity dates, high yield (percent; bills: high discount and investment rate; FRNs: high discount margin), coupon, bid-to-cover, offering, tendered and accepted amounts (USD), and indirect, direct and primary-dealer takedown (percent of the competitive amount accepted). tail_bp is null: the record has no when-issued yield. Results post the auction day; held_range says where the held history starts. Newest first, up to limit. Call it for auction demand, foreign/indirect appetite or dealer take-up by tenor.","query_params":[{"name":"security_type","type":"string","enum":["Bill","Note","Bond","TIPS","FRN","CMB"],"description":"Note includes TIPS notes and FRNs and Bill includes cash management bills; TIPS, FRN and CMB select only those"},{"name":"term","type":"string","description":"e.g. 10-Year, 13-Week (matches the original term of a reopening too)"},{"name":"start","type":"string","description":"YYYY-MM-DD (default end - 180 days)"},{"name":"end","type":"string","description":"YYYY-MM-DD (default today); at most 10 years per call"},{"name":"limit","type":"int","default":100,"min":1,"max":500}],"admin":false,"display_name":"Treasury auction results","public_name":"macro_history_treasury_auctions"},{"name":"tengu_v3_macro_history_leading_indicators","method":"GET","path":"/api/v3/macro_history/leading_indicators","group":"v3","description":"OECD composite leading indicators, monthly, by country or area (US, China, G7, G20 and 18 more): amplitude-adjusted index, long-term average = 100 (above 100 and rising = growth above trend ahead), with the latest month and its one-month change. month is the reference month; a month publishes about six weeks after it starts, and the newest release's revised history is served (earlier vintages are not held). Held from 2020. Call it for turning points in the cycle across economies.","query_params":[{"name":"country","type":"string","description":"one country or area by name or code (US, UK, CHN...; default all); an unknown one is a 422 listing the names and codes accepted"},{"name":"start","type":"string","description":"YYYY-MM-DD (default end - 3 years)"},{"name":"end","type":"string","description":"YYYY-MM-DD (default today)"}],"admin":false,"display_name":"Leading indicators history","public_name":"macro_history_leading_indicators"},{"name":"tengu_v3_macro_history_chokepoints","method":"GET","path":"/api/v3/macro_history/chokepoints","group":"v3","description":"Daily ship transits and estimated cargo (metric tons) through 24 maritime chokepoints (Suez Canal, Panama Canal, Strait of Hormuz, Malacca, Bab el-Mandeb, Bosporus and more), by vessel type: tanker, container, dry bulk, general cargo, ro-ro and total. From IMF PortWatch satellite ship tracking, published about a week after the day; history from 2019. One chokepoint can span up to 8 years per call, all of them up to 92 days. Call it for shipping disruptions, energy flows or trade-volume nowcasts.","query_params":[{"name":"chokepoint","type":"string","description":"one chokepoint by name (default all); an unknown name is a 422 listing those held"},{"name":"start","type":"string","description":"YYYY-MM-DD (default end - 365 days for one chokepoint, 30 for all)"},{"name":"end","type":"string","description":"YYYY-MM-DD (default today)"}],"admin":false,"display_name":"Shipping chokepoints","public_name":"macro_history_chokepoints"},{"name":"tengu_v3_macro_history_series_catalog","method":"GET","path":"/api/v3/macro_history/series","group":"v3","description":"Catalogue of the 68 U.S. economic series served by macro_history_series: FRED series id, title, the source's unit, frequency and seasonal-adjustment labels, the date a rebased series' current unit took effect, value basis and the newest observation held with its freshness. Covers Treasury yields and curve spreads, policy and money-market rates, inflation and breakevens, money and the Fed balance sheet, credit spreads and financial conditions, FX and oil, output, labour, housing and GDP nowcasts. Call it to find a series id and its unit before asking for its history.","query_params":[],"admin":false,"display_name":"Economic series list","public_name":"macro_history_series_catalog"},{"name":"tengu_v3_macro_history_series","method":"GET","path":"/api/v3/macro_history/series/{series_id}","group":"v3","description":"One U.S. economic series' observations by FRED series id (e.g. CPIAUCSL, DGS10, UNRATE, GDPNOW), with the source's own unit, frequency and seasonal-adjustment labels. Each value says its value_basis: first_release (as first published, with the instant it became public, so a backtest sees what was known then), earliest_archived_vintage (older than the source's vintage archive), latest_estimate (nowcasts) or as_of_pull. Every value is in today's unit: one first published in an earlier base year (chained 2012 dollars, 2012=100) is withheld with published_in_an_earlier_base_year. Default window by frequency; up to 5,000 newest points. An unknown id is a 422 listing the ids.","path_params":["series_id"],"query_params":[{"name":"start","type":"string","description":"YYYY-MM-DD (default depends on frequency)"},{"name":"end","type":"string","description":"YYYY-MM-DD (default today)"}],"admin":false,"display_name":"Economic series history","public_name":"macro_history_series"},{"name":"tengu_v3_macro_history_sp500_valuation","method":"GET","path":"/api/v3/macro_history/sp500_valuation","group":"v3","description":"S&P 500 valuation, monthly since 1871: CAPE (price over ten years of inflation-adjusted earnings), trailing P/E (ratios), dividend yield and earnings yield (percent), each with its definition. Values are dated the first of the month; the current month's row is provisional (provisional true) until the month ends. Call it for valuation regimes, long-horizon return context or comparing today's multiple with history.","query_params":[{"name":"metric","type":"string","description":"comma list of cape, pe, dividend_yield, earnings_yield (default all)"},{"name":"start","type":"string","description":"YYYY-MM-DD (default end - 20 years)"},{"name":"end","type":"string","description":"YYYY-MM-DD (default today)"}],"admin":false,"display_name":"S&P 500 valuation history","public_name":"macro_history_sp500_valuation"},{"name":"tengu_v3_estimates_history_earnings_surprises","method":"GET","path":"/api/v3/estimates_history/earnings_surprises/{ticker}","group":"v3","description":"A ticker's quarterly EPS estimate vs actual as the estimates feed published them, from the archive: period_end (calendar quarter end), fiscal labels, fiscal_quarter_end, consensus EPS, actual EPS (the estimates vendor's adjusted EPS, eps_basis_note), surprise per share and percent, and when each row was taken. freshness is measured from fiscal_quarter_end where known. Held as reported from 2026-09-23 (about four quarters then, one more each quarter). Every row is on today's share basis: quarters taken before a split are restated by its exact ratio from the corporate-actions record; a row whose estimate and actual sit a recorded split apart is withheld with split_basis_mismatch. With no recorded split, a gap of 4 or more whole times is withheld the same way; at 2 or 3 the row is served, flagged split_check with surprise_status basis_unconfirmed (its beat or miss holds only if no split applies). Stock dividends are not in that record. An unlisted symbol is a 404 unknown_ticker.","path_params":["ticker"],"query_params":[{"name":"limit","type":"int","default":20,"min":1,"max":80,"description":"quarters, newest first"}],"admin":false,"display_name":"EPS surprise history","public_name":"estimates_history_earnings_surprises"},{"name":"tengu_v3_estimates_history_recommendations","method":"GET","path":"/api/v3/estimates_history/recommendations/{ticker}","group":"v3","description":"A ticker's monthly analyst rating counts from the estimates feed's archive: strong buy, buy, hold, sell and strong sell, their sum, and the buy and sell shares (percent of the sum). month is the tally's month; the feed publishes it during the month. Call it to see how the rating mix moved; for price targets and rating actions use intel_analyst_consensus. An unlisted symbol is a 404 unknown_ticker.","path_params":["ticker"],"query_params":[{"name":"months","type":"int","default":24,"min":1,"max":120}],"admin":false,"display_name":"Analyst rating counts","public_name":"estimates_history_recommendations"},{"name":"tengu_v3_estimates_history_insider_sentiment","method":"GET","path":"/api/v3/estimates_history/insider_sentiment/{ticker}","group":"v3","description":"A ticker's monthly insider sentiment from the estimates feed's archive: mspr, the feed's monthly share purchase ratio from -100 (insiders only sold) to +100 (only bought), and net_share_change (shares bought minus sold). A month with no insider transactions has no row; months the feed files ahead of the current one are not served. For the filings themselves use origin_insider_flow. An unlisted symbol is a 404 unknown_ticker.","path_params":["ticker"],"query_params":[{"name":"months","type":"int","default":24,"min":1,"max":120}],"admin":false,"display_name":"Insider sentiment history","public_name":"estimates_history_insider_sentiment"},{"name":"tengu_v3_credit_indices","method":"GET","path":"/api/v3/credit/indices","group":"v3","description":"Credit-index composites — the credit market's VIX-equivalents: CDX (NA IG/HY) + iTraxx (Europe/Asia/SovX) daily composite spreads and prices by series/version/tenor, 2018 to T-2. Call it for credit-market risk appetite, spread-widening episodes, or cross-asset stress context. Spreads and coupons are decimal fractions with *_bps twins, prices a fraction of par with compositeprice_pct_of_par (`units`). When the row limit cuts the window, truncated/has_more are true, the partial oldest session is dropped and dates_covered lists what is served. FRESHNESS IS T-2 (daily composite) — never present as realtime.","query_params":[{"name":"family","type":"string","enum":["CDX","ITRAXX-EUROPE","ITRAXX-ASIA","ITRAXX-SOVX"]},{"name":"index_ticker","type":"string"},{"name":"days","type":"int","default":7,"min":1,"max":90},{"name":"limit","type":"int","default":2000,"min":1,"max":5000}],"admin":false,"public_name":"credit_indices"},{"name":"tengu_v3_credit_cds_history","method":"GET","path":"/api/v3/credit/cds/{ticker}/history","group":"v3","description":"Daily 5Y single-name CDS spread history: composite par spreads (raw + bps), market-implied default probability, average/implied agency rating. default_prob is the 5-year cumulative risk-neutral probability implied by the spread (`units`). Call it for how default risk has trended (tengu_v3_credit is the one-call snapshot). Coverage 2005 to end-2025, 5Y tenor; tickers match the equity symbol for liquid US names (F, T, GE...).","path_params":["ticker"],"query_params":[{"name":"start","type":"string","description":"ISO date; series start (default end - 365 days)"},{"name":"end","type":"string","description":"ISO date; series end (default today)"},{"name":"limit","type":"int","default":1000,"min":1,"max":5000}],"admin":false,"display_name":"CDS spread history","capability_tags":["heavy"],"public_name":"credit_cds_history"},{"name":"tengu_v3_credit_ratings","method":"GET","path":"/api/v3/credit/ratings/{ticker}","group":"v3","description":"Full S&P rating-action history for one issuer's debt — every licensed institutional action (new rating, upgrade, downgrade, outlook/creditwatch change) with from/to symbols, newest first. Use when asked what a company is rated or when/why it was up/downgraded. Equity ticker is resolved to the issuer CUSIP-6 via the fundamentals security master; actions are instrument-level, so several rows can share a date. No rows is never 'unrated' (empty_means_unrated: false): debt issued by subsidiaries, or by a depositary receipt's foreign issuer, is filed under other identifiers (empty_reason, coverage_note).","path_params":["ticker"],"query_params":[{"name":"limit","type":"int","default":200,"min":1,"max":5000}],"admin":false,"display_name":"Credit ratings","public_name":"credit_ratings"},{"name":"tengu_v3_credit_loans","method":"GET","path":"/api/v3/credit/loans/{ticker}","group":"v3","description":"Syndicated loan book for one borrower: per-facility size, type (revolver/term), maturity, security/seniority, all-in drawn/undrawn spread bps, covenants; include_lenders adds recent-facility syndicate allocations. Private-credit complement to the TRACE bond tape; call for leverage, facility or covenant questions; match on borrower ticker. data_through is the borrower's newest facility in the archive; when that is over two years old coverage_status is 'historical' and the active counts are withheld (the list is the historical record, not today's bank lines).","path_params":["ticker"],"query_params":[{"name":"limit","type":"int","default":100,"min":1,"max":1000},{"name":"include_lenders","type":"bool","default":false,"description":"also return syndicate lender allocations for the most recent facilities"}],"admin":false,"display_name":"Loan book","public_name":"credit_loans"},{"name":"tengu_v3_factor_characteristics","method":"GET","path":"/api/v3/factors/characteristics/{ticker}","group":"v3","description":"The stock's most recent monthly firm-characteristic vector in the academic firm-characteristic archive (~460 columns incl. the 102 published anomaly characteristics — size, book-to-market, momentum, liquidity, accruals, analyst coverage, plus macro interactions). The archive is lagged (its newest rows can be well over a year old), so this is usually history, not a current reading: `freshness` gives data_through and data_lag_days and grades the row `archival` when it is more than two months older than today (or than as_of). Call it for the full quant feature set of one stock as of the archive's newest month, or a point-in-time vector via as_of. Columns that contradict the row's own market_cap, and a book-value block (be, bm, ptb, roe) whose book value and book-to-market disagree (with num_analysts, a suspected fill beside it), are null, with the reason in withheld_characteristics. Ticker is resolved to its internal security key automatically. The panel's realized forward-return labels (fwd_*, excess_ret_1m: the return AFTER the row's date) are not characteristics and are withheld; outcome_labels_withheld names them.","path_params":["ticker"],"query_params":[{"name":"as_of","type":"string","description":"ISO date — return the latest monthly vector at or before this date (default: latest month)"}],"admin":false,"display_name":"Factor characteristics","public_name":"factor_characteristics"},{"name":"tengu_v3_factor_characteristic_history","method":"GET","path":"/api/v3/factors/characteristics/{ticker}/history","group":"v3","description":"Monthly time series of ONE factor characteristic for a stock (e.g. mom_12m, bm, mktcap, realized_vol, sue, turnover), newest first; the archive is lagged and `freshness` says how far the series reaches. Call it to chart how an anomaly signal evolved for a name or to compare signal drift across names; a typo in `char` returns 422 with the full list of valid column names. A month whose value contradicts the same row's market cap or book value is null with withheld_reason, as the vector tool withholds it. A forward-return label (fwd_*, excess_ret_1m) is not a characteristic: 422 unknown_characteristic with reason realized_forward_return.","path_params":["ticker"],"query_params":[{"name":"char","type":"string","required":true,"description":"characteristic column to chart (required)"},{"name":"start","type":"string","description":"ISO date series start (default: full history)"},{"name":"end","type":"string","description":"ISO date series end (default: latest month)"},{"name":"limit","type":"int","default":600,"min":1,"max":1200}],"admin":false,"display_name":"Factor signal history","capability_tags":["heavy"],"public_name":"factor_characteristic_history"},{"name":"tengu_v3_factor_exposures","method":"GET","path":"/api/v3/factors/exposures/{ticker}","group":"v3","description":"Rolling 60-month factor betas (Fama-French 5 + momentum) for one stock: beta_mkt/smb/hml/rmw/cma/umd with alpha (monthly), idiosyncratic/total volatility (annualised) and regression R², plus the monthly history of those loadings; `units` states each. The archive is lagged: `freshness` gives data_through and grades the newest row `archival` when it is more than two months old, and an archival row is the stock's factor profile as of that date, not its current exposure.","path_params":["ticker"],"query_params":[{"name":"limit","type":"int","default":60,"min":1,"max":1200,"description":"months of beta history to return (default 5y)"}],"admin":false,"display_name":"Factor exposures","public_name":"factor_exposures"},{"name":"tengu_v3_governance","method":"GET","path":"/api/v3/governance/{ticker}","group":"v3","description":"One-call corporate-governance dossier: board size + composition (independent vs executive directors, current members), director interlocks with other boards, restatement record, auditor-change history, and the latest year's executive compensation (CEO/CFO and top-5 named officers). exec_comp.year is the archive's fiscal-year number (a year ending January-May carries the previous calendar year's): quote exec_comp.fiscal_year (the company's own label) and fiscal_year_end_month instead (fiscal_year_reason says why a label is missing). board_size counts directors; a placeholder-dated row with no board role is listed under board.not_counted. Call it for any management-quality, board-oversight or comp question; blocks degrade independently. For graded forensic red flags use /api/v3/intel/accounting_flags.","path_params":["ticker"],"query_params":[],"admin":false,"display_name":"Governance dossier","public_name":"governance_dossier"},{"name":"tengu_v3_accounting_flags","method":"GET","path":"/api/v3/intel/accounting_flags/{ticker}","group":"v3","description":"Forensic accounting red flags with plain-language reasons, from the forensic-audit dataset: fraud/SEC-investigation/adverse restatements, auditor resignations, going-concern or disagreement auditor changes, auditor churn, audit-fee swings >50% yoy, and non-audit-fee dominance (independence risk). Each flag carries severity + reason with the evidence rows attached. Call it before trusting reported financials on any name with earnings-quality doubts (e.g. SMCI returns the 2024 EY-resignation cluster); an empty flags list on a covered name is a genuinely clean record.","path_params":["ticker"],"query_params":[{"name":"limit","type":"int","default":50,"min":1,"max":500,"description":"max rows per evidence block"}],"admin":false,"display_name":"Accounting red flags","public_name":"accounting_flags"},{"name":"tengu_v3_news_sentiment_history","method":"GET","path":"/api/v3/news/sentiment_history/{ticker}","group":"v3","description":"Daily aggregated news sentiment for one company back to 2000 — mean event sentiment (ESS), event count and mean relevance per day from the news-analytics archive (2000-2025) stitched with the live feed. Call it for long-run sentiment regimes or news reaction around past events; for today's headlines use the /news routes instead. The live feed arrives in monthly batches: data_through is its newest day (the archive's end for a window inside the archive), is_stale is true once a month is due (due_through) and not held, days after data_through are not held yet (coverage.not_covered_after), and a window starting after it answers warning window_after_coverage, which means not held yet, not no news. When the archive or live tail cannot be read it returns 503 upstream_unavailable (error_code warehouse_read_failed; not billed), never an empty series.","path_params":["ticker"],"query_params":[{"name":"start","type":"string","description":"First day YYYY-MM-DD (default 1y before end; archive back to 2000)"},{"name":"end","type":"string","description":"Last day YYYY-MM-DD (default today)"},{"name":"min_relevance","type":"number","default":70.0,"min":0,"max":100,"description":"Drop events below this news-analytics relevance (90+ = story is about the company)"},{"name":"entity","type":"string","description":"Exact news-analytics entity_name override — bypasses the ticker→name bridge"},{"name":"limit","type":"int","default":400,"min":1,"max":10000}],"admin":false,"display_name":"News sentiment history","capability_tags":["heavy"],"public_name":"news_sentiment_history"},{"name":"tengu_v3_intel_sec13f_history","method":"GET","path":"/api/v3/intel/sec13f_history/{ticker}","group":"v3","description":"Institutional-holder history — a holder × quarter matrix of 13F positions (shares per quarter-end + latest value, each holder's equity lots summed) from the institutional 13F archive, read on the stock's share-class CUSIP. Call it to track when funds built or exited a stock across quarters; for only the latest snapshot use /intel/sec13f. shares_by_quarter is on the latest quarter's share basis across stock splits (split_adjustment; the archive's own counts in shares_by_quarter_as_reported). suspect_quarters flags a quarter the archive probably holds wrong (suspect_quarter_legend), and missing_known_filers names manager families it does not carry. The archive ends a quarter behind EDGAR: latest_quarter, vendor_ceiling and is_stale say so. When the archive cannot be read it returns 503 upstream_unavailable (error_code archive_read_failed; not billed), never an empty matrix.","path_params":["ticker"],"query_params":[{"name":"quarters","type":"int","default":12,"min":1,"max":40,"description":"How many quarters back"},{"name":"top","type":"int","default":25,"min":1,"max":100,"description":"Top N holders by latest position value"}],"admin":false,"display_name":"13F holder history","capability_tags":["heavy"],"public_name":"intel_sec13f_history"},{"name":"tengu_v3_intel_street_estimates_history","method":"GET","path":"/api/v3/intel/street_estimates_history/{ticker}","group":"v3","description":"Analyst-level estimate revision timeline — every individual broker estimate (announce/revision dates, analyst id, fiscal period, value, realised actual) from the analyst-estimate detail archive back to 1980. Call it to reconstruct how the street walked numbers up or down before a print; for the consensus snapshot use /intel/street_estimates. Rows are the newest `limit` in the window, oldest first. data_through is the archive's newest announcement date and is_stale grades it; window_after_coverage true means the window starts after the archive ends, so no rows means not held, not no estimates. A failed read is error warehouse_read_failed.","path_params":["ticker"],"query_params":[{"name":"measure","type":"string","default":"EPS","description":"analyst-estimate measure code (EPS, SAL, EBI, CPS, DPS, GRM, NET, PRE, ROA, ROE ...)"},{"name":"days","type":"int","default":365,"min":1,"max":9500,"description":"Announcement-date lookback window"},{"name":"limit","type":"int","default":2000,"min":1,"max":50000}],"admin":false,"display_name":"Estimate revisions","capability_tags":["heavy"],"public_name":"intel_street_estimates_history"},{"name":"tengu_v3_intel_street_estimates_guidance","method":"GET","path":"/api/v3/intel/street_estimates_guidance/{ticker}","group":"v3","description":"Management guidance history — every company-issued guidance range (measure, period, low/high, announce date, street consensus at that date) from the analyst-estimate Guidance archive. Call it to compare what management promised vs what the street expected, or to study guidance-cut reactions. Rows are the newest `limit` in the window, oldest first; data_through, is_stale and window_after_coverage say how far the archive runs. A failed read is error warehouse_read_failed.","path_params":["ticker"],"query_params":[{"name":"measure","type":"string","description":"Filter to one analyst-estimate measure code (EPS, SAL, EBI, ...); default all"},{"name":"start","type":"string","description":"Earliest announce date YYYY-MM-DD (default: all history)"},{"name":"limit","type":"int","default":500,"min":1,"max":5000}],"admin":false,"display_name":"Guidance history","public_name":"intel_street_estimates_guidance"},{"name":"tengu_v3_prices_history","method":"GET","path":"/api/v3/prices/history/{ticker}","group":"v3","description":"Survivorship-bias-free daily price history — archive daily closes, returns, volume and cumulative split adjustment factors (cfacpr/cfacshr) 2000-2024, stitched with live daily bars 2025→today, plus the delisting record. ONE basis on every row: prc is the price as traded, prc/cfacpr is on today's share basis (vol*cfacshr likewise); price_basis says which live rows were restored to as-traded, and a step no split explains is refused (503 price_series_discontinuous), never served. ret is the total return (dividends on their ex-date) and retx the price return, on archive and live rows alike; if the live dividend record cannot be read, live ret is null and returns_basis says why. Rows before 2000 carry null cfacpr/cfacshr; an adjustment block then names them, and ret/retx stay valid. interval defaults to 1d — omit it or pass interval=1d. A missing grain used to 504; the route is daily-only. A small limit (e.g. 5) returns the newest live daily bars without scanning the archive. Intraday intervals 422 to /api/v3/tape/bars/{ticker}?date=YYYY-MM-DD. Not /fundamentals/prices (vendor OHLCV) and not /reference/history (identifier timeline).","path_params":["ticker"],"query_params":[{"name":"start","type":"string","description":"First day YYYY-MM-DD (default: the last 365 days; the archive starts 2000-01-01)"},{"name":"end","type":"string","description":"Last day YYYY-MM-DD (default today)"},{"name":"limit","type":"int","default":15000,"min":1,"max":15000}],"admin":false,"display_name":"Deep price history","capability_tags":["heavy"],"public_name":"prices_history"},{"name":"tengu_v3_prices_corporate_actions","method":"GET","path":"/api/v3/prices/corporate_actions/{ticker}","group":"v3","description":"Complete corporate-action history — every cash dividend, stock split and distribution back to first listing, from the current research-grade distributions file (not the retired one that stopped at 2024-12-31): one row per event in its newest version known at as_of (default now), with divamt, facpr/facshr factors, declare/ex/record/pay dates, type codes (distype FRS = split or stock dividend; distcd is null) and the version's known_from. coverage.current_through is the newest ex-date held; the file is refreshed by hand, so it is not live. known_from is the vendor's availability rule, not when the platform saw the row (see clock). A failed read is a 503 (warehouse_read_failed; not billed), never an empty history. Call it to build adjusted price series or dividend-growth analyses.","path_params":["ticker"],"query_params":[{"name":"start","type":"string","description":"Earliest ex-date YYYY-MM-DD (default: all history)"},{"name":"limit","type":"int","default":1000,"min":1,"max":5000,"description":"Max rows, oldest ex-date first"},{"name":"as_of","type":"string","description":"Knowledge instant YYYY-MM-DD (end of that UTC day) or ISO 8601: each event in its newest version known by then. Default now"}],"admin":false,"display_name":"Corporate actions","public_name":"prices_corporate_actions"},{"name":"tengu_v3_intel_short_interest_history","method":"GET","path":"/api/v3/intel/short_interest_history/{ticker}","group":"v3","description":"Deep short-selling history — daily off-exchange short-volume series (short vs total shares across FINRA venues + short ratio, back to 2006) plus the bi-monthly short-interest series from a securities-data vendor's file (newest version of each settlement). daily_coverage and bimonthly_coverage state each series' end (data_through), age and is_stale; the daily archive lags by months. The bi-monthly block lists the settlement dates the source holds but WITHHOLDS its share counts (shortint and shortintadj are null; bimonthly_coverage.withheld_reason says why): they disagree with the exchange-reported short interest. For shares held short use /origin/short_activity or /intel/short_interest. Call it for multi-year squeeze setups or shorting pressure around events (the daily short-volume series); for recent daily short volume use /origin/short_activity, and for today's borrow cost /intel/borrow_cost.","path_params":["ticker"],"query_params":[{"name":"start","type":"string","description":"First day YYYY-MM-DD for the daily series (default 1y before end)"},{"name":"end","type":"string","description":"Last day YYYY-MM-DD (default today)"},{"name":"limit","type":"int","default":400,"min":1,"max":5000}],"admin":false,"display_name":"Short interest history","capability_tags":["heavy"],"public_name":"intel_short_interest_history"},{"name":"tengu_v3_workforce_momentum","method":"GET","path":"/api/v3/workforce/momentum/{ticker}","group":"v3","description":"Monthly EMPLOYMENT MOMENTUM for one company — headcount trend, hiring vs attrition and salary level, from a monthly workforce panel rather than an annual filing. Returns the latest month's headcount with its hiring, attrition and net-hiring rates (percent of headcount per month plus annualized twins), 1m/3m/12m headcount growth, average salary per employee (USD per year), and the full monthly series. Call it to see a company expanding or shrinking MONTHS before the next 10-K, or to catch attrition rising while headcount looks flat. Values are modelled estimates, not company-reported figures, and the level can sit far from the reported headcount; read reconciled changes as the signal. Growth is served only when the headcount change agrees with hires minus departures over the same months; otherwise it is null with the stock-implied and flow-implied figures (and, when the latest month itself does not reconcile, the growth to the last month that does). The panel is being backfilled: `coverage` reports the months actually present and any lookback the panel cannot support returns null with a reason — never an interpolated number. Ticker is not unique across venues; the response names the entity served and lists symbol_collisions you can pin with employer_id.","path_params":["ticker"],"query_params":[{"name":"months","type":"int","default":24,"min":2,"max":120,"description":"Months of monthly series returned (newest first)"},{"name":"employer_id","type":"int","min":1,"description":"Pin an exact employer when the symbol is ambiguous (take it from `symbol_collisions`)"}],"admin":false,"display_name":"Hiring momentum","capability_tags":["heavy"],"public_name":"workforce_momentum"},{"name":"tengu_v3_workforce_layoffs","method":"GET","path":"/api/v3/workforce/layoffs/{ticker}","group":"v3","description":"WARN-Act LAYOFF FILINGS for one company — the public notices an employer must file WEEKS BEFORE a cut, so they lead the press release and the next earnings call. Returns each filing (notice date, effective date, employees affected, site city/state, layoff type) newest first, plus TRUE window totals, a month-by-month series and the largest single filing; with_workforce also sizes the total against estimated headcount and names the headcount month used. Call it as a downside early-warning, or to confirm the scale of an announced restructuring — filings are SITE-level, so one restructuring appears as many rows. Coverage is US WARN notices from 1989 forward including forward-dated notices; only employers matched to a listed symbol are reachable by ticker, so an empty result is not proof there were no layoffs. A single notice far above the employer's modelled headcount (more than 5x, or more than 2x beside a smaller row for the same site and day) is quarantined: listed, flagged, counted in no total. Any other notice above it is flagged exceeds_modelled_headcount and still counted. Every answer states where the filing archive ends (data_through, is_stale); a window that starts after it, or mostly lies after it, carries a warning, and an empty one is 'not covered', never 'no filings'.","path_params":["ticker"],"query_params":[{"name":"months","type":"int","default":24,"min":1,"max":480,"description":"Lookback window in calendar months"},{"name":"limit","type":"int","default":200,"min":1,"max":2000,"description":"Filing rows returned; the totals always cover the FULL window, not just this page"},{"name":"with_workforce","type":"bool","default":true,"description":"Also size the total against estimated headcount"},{"name":"employer_id","type":"int","required":false,"description":"Pin a specific employer when the symbol is shared by more than one (see symbol_collisions). Answers are returned with identity_verified=false, since pinning asserts an identity we could not prove"}],"admin":false,"display_name":"Layoff filings","capability_tags":["heavy"],"public_name":"workforce_layoffs"},{"name":"tengu_v3_workforce_layoff_screen","method":"GET","path":"/api/v3/workforce/layoff_screen","group":"v3","description":"CROSS-SECTIONAL LAYOFF SCREEN — which listed companies filed WARN-Act layoff notices in the last N days, ranked by employees noticed. One row per employer (ticker + employer_id: company, filing count, employees noticed, first/latest event date, states touched, largest single filing) across the whole listed universe. Call it for 'who is cutting right now' — notices are filed weeks before the cut, so this surfaces restructurings before the press release. A single notice far above the employer's modelled headcount (more than 5x, or more than 2x beside a smaller row for the same site and day) is quarantined and counts toward no figure or rank; an employer whose every notice was quarantined is listed apart. The answer states where the filing archive ends (data_through, is_stale), with a warning when the window starts after it or mostly lies after it. Only employers matched to a listed symbol appear; most WARN filers are private and are excluded by design. For one company's filings use /workforce/layoffs/{ticker}.","query_params":[{"name":"days","type":"int","default":90,"min":1,"max":1825,"description":"Lookback window in days"},{"name":"min_employees","type":"int","default":0,"min":0,"max":1000000,"description":"Only employers at or above this total employees noticed"},{"name":"state","type":"string","description":"US state, full name exactly as filed, e.g. 'California' (a two-letter code matches nothing)"},{"name":"limit","type":"int","default":100,"min":1,"max":1000}],"admin":false,"display_name":"Layoff screen","public_name":"workforce_layoff_screen"},{"name":"tengu_v3_workforce_momentum_screen","method":"GET","path":"/api/v3/workforce/momentum_screen","group":"v3","description":"CROSS-SECTIONAL HIRING SCREEN — rank listed employers by headcount growth between the panel's latest month and N months earlier: ticker, company, headcount then and now, percent and absolute change, latest hiring and attrition rates and average salary, sorted fastest-growing or fastest-shrinking. This is the workforce factor as a screen — who is actually staffing up (or quietly shrinking) months before it reaches a filing. Only employers whose headcount change is explained by their own hires minus departures are ranked; the rest (employer re-mappings, revised months) are listed apart as excluded_entity_artefacts with the gap. The monthly panel is MID-BACKFILL, so a months_back longer than the loaded window returns an explicit warning listing the lookbacks that ARE available — never a silently shortened comparison.","query_params":[{"name":"months_back","type":"int","default":1,"min":1,"max":36,"description":"Compare the latest month against this many months earlier"},{"name":"min_headcount","type":"float","default":1000,"min":0,"description":"Drop micro-employers below this estimated headcount"},{"name":"order","type":"string","default":"fastest_growing","enum":["fastest_growing","fastest_shrinking"]},{"name":"limit","type":"int","default":100,"min":1,"max":500}],"admin":false,"display_name":"Hiring screen","capability_tags":["heavy"],"public_name":"workforce_momentum_screen"},{"name":"tengu_v3_supply_chain_relationships","method":"GET","path":"/api/v3/supply_chain/relationships/{ticker}","group":"v3","description":"The SUPPLY-CHAIN GRAPH around one company — its customers, suppliers, competitors and partners in one call, each with the relationship's start date, whether it is still open, which side reported it, and revenue dependence where it was estimated. Both directions are merged and normalised to the queried company's point of view, so 'customers' includes companies that report THIS company as their supplier. Call it to map second-order exposure (whose earnings move when this name moves) or to find the listed suppliers behind a product cycle. Defaults to CURRENT relationships; status=all or as_of=YYYY-MM-DD gives history. One entry per counterparty by default (several records can back one pair) — group_by=record gives the underlying versions. revenue_percent belongs to the company named in revenue_percent_of_ticker, is an ESTIMATE on every row, and is present on only a minority of edges; coverage is reported per group.","path_params":["ticker"],"query_params":[{"name":"rel_type","type":"string","enum":["customers","suppliers","competitors","partners"],"description":"Restrict to one relationship group; omit for all four"},{"name":"status","type":"string","default":"current","enum":["current","all"],"description":"current = open relationships only (most history is closed)"},{"name":"as_of","type":"string","description":"YYYY-MM-DD point-in-time view (overrides status)"},{"name":"listed_only","type":"bool","default":false,"description":"Drop counterparties with no ticker (private companies)"},{"name":"group_by","type":"string","default":"counterparty","enum":["counterparty","record"]},{"name":"limit","type":"int","default":50,"min":1,"max":500},{"name":"company_id","type":"string","description":"Pin an exact entity when the symbol is ambiguous"}],"admin":false,"display_name":"Supply chain map","capability_tags":["heavy"],"public_name":"supply_chain_relationships"},{"name":"tengu_v3_supply_chain_revenue_dependence","method":"GET","path":"/api/v3/supply_chain/revenue_dependence/{ticker}","group":"v3","description":"REVENUE DEPENDENCE, both sides — the revenue-at-risk map around one company. `customer_concentration`: how much of THIS company's revenue each customer accounts for. `dependents_on_company`: other companies whose revenue depends on THIS one (e.g. a component maker that books most of its revenue from one handset vendor) — the list that reprices when this name changes its orders, and it is in no filing screen. Percentages are of the DEPENDENT company's revenue and every row names whose revenue it is, so the number can never be read backwards. Coverage is sparse and disclosed: only a minority of relationships carry an estimated percentage, so absence means UNKNOWN, never zero.","path_params":["ticker"],"query_params":[{"name":"status","type":"string","default":"current","enum":["current","all"]},{"name":"as_of","type":"string","description":"YYYY-MM-DD point-in-time view"},{"name":"min_percent","type":"float","default":0,"min":0,"max":100,"description":"Only rows at or above this percent of the dependent's revenue (percent, 0-100)"},{"name":"limit","type":"int","default":50,"min":1,"max":500},{"name":"company_id","type":"string","description":"Pin an exact entity when the symbol is ambiguous"}],"admin":false,"display_name":"Revenue dependence","capability_tags":["heavy"],"public_name":"supply_chain_revenue_dependence"},{"name":"tengu_v3_supply_chain_geo_revenue","method":"GET","path":"/api/v3/supply_chain/geo_revenue/{ticker}","group":"v3","description":"GEOGRAPHIC REVENUE EXPOSURE for one company — where the revenue actually comes from, estimated region by region and country by country for a fiscal period, with a per-row confidence score. This is the tariff / geopolitical lens: it answers 'how much of this company's revenue is China?' for names that never break that out. Returns the requested hierarchy layer as `regions`, the country leaves as `countries`, concentration metrics (largest country share and an HHI), the period served and the other periods available. ?country=CN,TW returns a per-period HISTORY for exactly those countries. Each layer sums to 100 on its own, so never add a region to a country. Amounts carry NO currency code in the source and the reporting currency can change between periods, so compare on PERCENT, not amount. Estimates, not company-reported segments — for reported segments use /fundamentals/segments/{ticker}.","path_params":["ticker"],"query_params":[{"name":"period","type":"string","description":"Fiscal period end YYYY-MM-DD; omit for the latest available"},{"name":"layer","type":"int","default":1,"min":0,"max":4,"description":"Hierarchy layer returned as `regions` (0 = world, 4 = country)"},{"name":"country","type":"string","description":"Comma-separated ISO alpha-2 codes; switches to per-period history"},{"name":"top_countries","type":"int","default":25,"min":0,"max":250},{"name":"company_id","type":"string","description":"Pin an exact entity when the symbol is ambiguous"}],"admin":false,"display_name":"Revenue by country","capability_tags":["heavy"],"public_name":"supply_chain_geo_revenue"},{"name":"tengu_v3_fundamentals_pit","method":"GET","path":"/api/v3/fundamentals/pit/{ticker}","group":"v3","description":"WHAT THE MARKET ACTUALLY KNEW on a given date — as-FIRST-REPORTED quarterly financials for a ticker as they stood on `as_of`: for each fiscal period, the latest published version whose knowledge date is on or before that day. Later restatements are excluded BY CONSTRUCTION, which is what makes this safe to backtest on — the ordinary financials endpoints serve the restated view and will leak look-ahead. Each period also reports whether it has been restated since and what the figure reads today, so you are never silently handed a stale number. Omit as_of for the current view. Figures are in MILLIONS of each filing's own reporting currency (carried per period) — never assume USD.","path_params":["ticker"],"query_params":[{"name":"as_of","type":"string","description":"Knowledge date YYYY-MM-DD; omit for the current restated view"},{"name":"periods","type":"int","default":8,"min":1,"max":60,"description":"Fiscal periods returned, newest first"},{"name":"indfmt","type":"string","description":"Industry format key (advanced; the dominant variant is chosen for you)"},{"name":"consol","type":"string","description":"Consolidation key (advanced)"},{"name":"popsrc","type":"string","description":"Population-source key (advanced)"},{"name":"datafmt","type":"string","description":"Data format key (advanced)"}],"admin":false,"display_name":"Point-in-time financials","capability_tags":["heavy"],"public_name":"fundamentals_pit"},{"name":"tengu_v3_fundamentals_pit_vintages","method":"GET","path":"/api/v3/fundamentals/pit/{ticker}/vintages","group":"v3","description":"THE RESTATEMENT TRAIL for one fiscal quarter — every published version of the period in order, each with the day it became the live view, the day it was superseded, and exactly WHICH line items changed from the previous version. Call it to check whether a figure you are relying on has been quietly revised, and by how much: a quarter can be restated several times, and only the trail shows it. The still-current version reports a null supersede date rather than a far-future sentinel. Omit datadate for the most recent quarter held.","path_params":["ticker"],"query_params":[{"name":"datadate","type":"string","description":"Fiscal period end YYYY-MM-DD; omit for the latest quarter held"},{"name":"indfmt","type":"string","description":"Industry format key (advanced)"},{"name":"consol","type":"string","description":"Consolidation key (advanced)"},{"name":"popsrc","type":"string","description":"Population-source key (advanced)"},{"name":"datafmt","type":"string","description":"Data format key (advanced)"}],"admin":false,"display_name":"Restatement history","capability_tags":["heavy"],"public_name":"fundamentals_pit_vintages"},{"name":"tengu_v3_fundamentals_pit_coverage","method":"GET","path":"/api/v3/fundamentals/pit_coverage","group":"v3","description":"The honest bounds of the point-in-time primitive: how many published versions are held, for how many companies, the span of KNOWLEDGE dates (which is what an as_of query can answer) and the span of fiscal periods covered. Call it before trusting an as_of earlier than the archive starts — outside the knowledge span the answer is 'not knowable here', not 'no data'. Pass a ticker for per-company bounds.","query_params":[{"name":"ticker","type":"string","description":"Per-company coverage; omit for archive-wide"}],"admin":false,"display_name":"Point-in-time coverage","public_name":"fundamentals_pit_coverage"},{"name":"tengu_v3_intel_insider_flow","method":"GET","path":"/api/v3/intel/insider_flow/{ticker}","group":"v3","description":"INSIDER TRANSACTIONS SPLIT BY WHETHER THE TRADE WAS PRE-SCHEDULED — Form 4/5 activity for one company with the metadata free feeds drop: the Rule 10b5-1 flag and the filing lag. Sales made under a 10b5-1 plan were scheduled in advance and carry NO view, so they are aggregated separately from discretionary trades and never blended into one 'net insider flow'; a third bucket holds rows with no plan flag, which is unknown, not discretionary. Only open-market buys and sells enter the flow buckets — grants, option exercises and tax-withholding are counted apart. A Form 4/A or 5/A that restates an earlier filing's lines replaces them in every aggregate (superseded_by_amendment on the original line). Share counts are as filed, NOT split-adjusted (shares_split_adjusted is null): compare USD values across a split. The plan flag is the data vendor's coding, not the filing's own checkbox. On an indirect line the archive's holdings-after figure is the owner's total across indirect accounts, served as owner_indirect_holdings_after. Use as_of to reproduce what was PUBLIC on a date: it filters on the filing date, the only correct as-of key for insider data (a trade-date filter leaks late-filed trades). An unknown symbol is a 404 unknown_ticker.","path_params":["ticker"],"query_params":[{"name":"start","type":"string","description":"Transaction-date window start YYYY-MM-DD; omit both for the latest filings held"},{"name":"end","type":"string","description":"Transaction-date window end; with start it spans at most 1095 days"},{"name":"as_of","type":"string","description":"Only filings PUBLIC by this date (filters on filing date)"},{"name":"record_type","type":"string","enum":["nonderiv","deriv"],"description":"nonderiv = common stock, deriv = options/RSUs; omit for both"},{"name":"limit","type":"int","default":200,"min":1,"max":2000,"description":"Transaction rows returned; the flow aggregates always cover the FULL window, not just this page"}],"admin":false,"display_name":"Insider flow (10b5-1 split)","public_name":"intel_insider_flow"},{"name":"tengu_v3_intel_insider_form144","method":"GET","path":"/api/v3/intel/insider_form144/{ticker}","group":"v3","description":"INSIDER INTENT-TO-SELL NOTICES — supply before it hits the tape. Form 144 is filed BEFORE a sale of restricted or control stock, so it is forward-looking: who intends to sell, roughly how many shares, through which broker, at what notified market value, and how the stock was acquired. Call it to see overhang building ahead of the completed sales, which only show up later in the Form-4 flow. A notice is an INTENT — it may be executed smaller, later, or not at all, so never treat notified value as realised selling. notice_date is the SEC filing date. A notice repeated by a later filing (a 144/A) is totalled once and marked superseded_by_later_filing, plus superseded_by_amendment (the amending filing's id, or its filing date when the id is missing) when that filing is an amendment; proposed_shares_total is as filed, not split-adjusted. An unknown symbol is a 404 unknown_ticker.","path_params":["ticker"],"query_params":[{"name":"start","type":"string","description":"Filing-date window start YYYY-MM-DD; omit both for the latest notices held"},{"name":"end","type":"string","description":"Filing-date window end"},{"name":"limit","type":"int","default":100,"min":1,"max":1000}],"admin":false,"display_name":"Intent-to-sell notices","public_name":"intel_insider_form144"},{"name":"tengu_v3_intel_insider_flow_coverage","method":"GET","path":"/api/v3/intel/insider_flow_coverage","group":"v3","description":"What insider history exists, for which dates, and how much of it carries a Rule 10b5-1 plan flag — rows by record type, distinct filers, the transaction- and filing-date spans, and the share of rows that actually carry the plan flag. Call it before reading a plan split as complete: rows without the flag are unknown, and this says how many there are. Pass a ticker for per-company coverage.","query_params":[{"name":"ticker","type":"string","description":"Per-company coverage; omit for archive-wide"}],"admin":false,"display_name":"Insider flow coverage","capability_tags":["heavy"],"public_name":"intel_insider_flow_coverage"},{"name":"tengu_v3_intel_top_shareholders_current","method":"GET","path":"/api/v3/intel/top_shareholders_current/{ticker}","group":"v3","description":"CURRENT INSTITUTIONAL HOLDERS of a company, largest first — holder-level positions with shares, market value (USD), percent of shares outstanding (percent, 0-100) and the change against the prior report, so new, increased, decreased and exited positions are visible. It is a holder-level archive distinct from /intel/top_shareholders and /intel/sec13f, and it can lag: freshness grades the quarter served against the quarter now due (expected_report_period, is_stale, quarters_behind, staleness_note), so quote the quarter served, never 'current'. A quarter-end that has not arrived carries quarter_has_ended=false. The archive is being backfilled, so the response lists every quarter it actually holds with its holder count, defaults to the most COMPLETE quarter and flags any quarter still loading rather than serving a half-loaded snapshot as fact. A 'new_position' can also be a renamed or re-coded holder entity, which the response says explicitly.","path_params":["ticker"],"query_params":[{"name":"quarter","type":"string","description":"Quarter-end YYYY-MM-DD; omit for the most COMPLETE quarter held"},{"name":"limit","type":"int","default":50,"min":1,"max":1000},{"name":"min_pct","type":"float","min":0,"max":100,"description":"Only holders at or above this percent of shares outstanding (percent, 0-100)"}],"admin":false,"display_name":"Top shareholders (current)","capability_tags":["heavy"],"public_name":"intel_top_shareholders_current"},{"name":"tengu_v3_intel_top_shareholders_coverage","method":"GET","path":"/api/v3/intel/top_shareholders_coverage","group":"v3","description":"How much institutional-ownership history has actually landed — per quarter: rows, securities and distinct holders held right now, plus a flag on any quarter still loading. Call it BEFORE treating a quarter-on-quarter change as a real position change: during a backfill a newly-opened quarter is incomplete, and a naive comparison makes every name look like it lost most of its holders. Pass a ticker for per-company coverage. Archive-wide is served from a materialised snapshot off the query path; a freshness block (as_of/stale/source_current/served_from) says how current it is and whether it came from the snapshot or a live recompute.","query_params":[{"name":"ticker","type":"string","description":"Per-company coverage; omit for archive-wide"}],"admin":false,"display_name":"Ownership data coverage","capability_tags":["heavy"],"public_name":"intel_top_shareholders_coverage"},{"name":"tengu_v3_ownership_holders","method":"GET","path":"/api/v3/ownership/holders/{ticker}","group":"v3","description":"Every 13F institutional holder of a US stock at one quarter-end, largest first: filer id, manager name, entity type code, shares, value in USD (shares x the close on price_date, the last trading day on or before the quarter-end), percent (0-100) of this share class's shares outstanding, and the change against the prior quarter (percent, on this quarter's split basis). Each row carries report_period and its filing_date. Omit report_period for the newest quarter whose filing deadline has passed; quarter_status says if a quarter is still filling. Quarterly, trailing EDGAR by one to two quarters. Share positions only (no put or call lines). A share count a stock split during the filing window leaves ambiguous is withheld, not guessed. Covers filers other 13F archives lack; missing_known_filers names any family still absent. Use for who owns a stock and how that changed.","path_params":["ticker"],"query_params":[{"name":"report_period","type":"string","description":"Quarter-end YYYY-MM-DD; omit for the newest settled quarter"},{"name":"limit","type":"int","default":50,"min":1,"max":500}],"admin":false,"display_name":"13F holders","capability_tags":["heavy"],"public_name":"ownership_holders"},{"name":"tengu_v3_ownership_changes","method":"GET","path":"/api/v3/ownership/changes/{ticker}","group":"v3","description":"Quarter-over-quarter 13F position changes in a US stock: new, added, reduced and exited positions per filer, largest share change first, with shares before and after, the change in shares and in percent, and both filing dates. The earlier quarter is restated to the later quarter's split basis; a change a split alone would explain is withheld. A change needs a filing in both quarters: holders missing a filing are counted in unreported_prev_holders / unreported_cur_holders, never served as buyers or sellers. counts gives the totals per change type. Quarterly, trailing EDGAR by one to two quarters. Use for institutional accumulation or distribution.","path_params":["ticker"],"query_params":[{"name":"report_period","type":"string","description":"Quarter-end YYYY-MM-DD; omit for the newest settled quarter"},{"name":"change_type","type":"string","default":"all","enum":["all","new","added","reduced","exited"]},{"name":"limit","type":"int","default":50,"min":1,"max":500}],"admin":false,"display_name":"13F position changes","capability_tags":["heavy"],"public_name":"ownership_changes"},{"name":"tengu_v3_ownership_filer","method":"GET","path":"/api/v3/ownership/filer/{filer_id}","group":"v3","description":"One 13F filer's holdings at a quarter-end, largest value first: CUSIP, the ticker at the report period, shares, value in USD (shares x the close on price_date) and percent (0-100) of that share class's shares outstanding, with the filing date, the position count and the total value of the positions priced. Omit report_period for the filer's newest quarter whose filing deadline has passed; a quarter the filer did not file answers status no_filing_for_quarter. Find filer_id with /ownership/filers or a holders row. Use to see a manager's book.","path_params":["filer_id"],"query_params":[{"name":"report_period","type":"string","description":"Quarter-end YYYY-MM-DD"},{"name":"limit","type":"int","default":100,"min":1,"max":500}],"admin":false,"display_name":"13F filer holdings","capability_tags":["heavy"],"public_name":"ownership_filer"},{"name":"tengu_v3_ownership_filers","method":"GET","path":"/api/v3/ownership/filers","group":"v3","description":"Find 13F filers by name: filer_id, manager name, entity type code, the newest report period and filing date held, and how many quarters it has filed. Only entities with a 13F-HR filing are listed. Use it to get the filer_id for /ownership/filer.","query_params":[{"name":"q","type":"string","required":true,"description":"Part of the filer's name, 2-80 characters"},{"name":"limit","type":"int","default":20,"min":1,"max":100}],"admin":false,"display_name":"13F filer search","public_name":"ownership_filers"},{"name":"tengu_v3_short_lending","method":"GET","path":"/api/v3/short/lending/{ticker}","group":"v3","description":"Daily securities-lending supply and demand for a US stock: lendable and actively lendable shares and USD value, shares and USD value on loan, shares on loan to short sellers, utilisation (percent 0-100), a 1-10 cost-of-borrow score and average loan tenure in days. Published about six trading days after the day; history from 2003. This is lending data, NOT short interest: finra_cross_check lists FINRA's settled short interest on each settlement date in the window beside short_loan_quantity and their ratio. For the headline fee use /intel/borrow_cost_history; for shares held short use /origin/short_activity. Window up to 366 days.","path_params":["ticker"],"query_params":[{"name":"start","type":"string","description":"YYYY-MM-DD; default end minus 90 days"},{"name":"end","type":"string","description":"YYYY-MM-DD; default today"},{"name":"limit","type":"int","default":120,"min":1,"max":400}],"admin":false,"display_name":"Securities lending","capability_tags":["heavy"],"public_name":"short_lending"},{"name":"tengu_v3_short_borrow","method":"GET","path":"/api/v3/short/borrow/{ticker}","group":"v3","description":"Daily borrow cost and availability for a US stock from a broker-lending feed: indicative borrow fee and rebate (percent per year) and shares available to borrow, one row per trading day (that day's last snapshot). Availability is reported only up to 10,000,000 shares; above that shares_available is null and shares_available_min is 10,000,000. History from 2026-03-16, updated each trading day. This is borrow supply, not short interest; FINRA's settled short interest in the window is listed for context. Use for hard-to-borrow and squeeze-cost checks. Window up to 366 days.","path_params":["ticker"],"query_params":[{"name":"start","type":"string","description":"YYYY-MM-DD; default end minus 90 days"},{"name":"end","type":"string","description":"YYYY-MM-DD; default today"},{"name":"limit","type":"int","default":120,"min":1,"max":400}],"admin":false,"display_name":"Borrow fee & availability","capability_tags":["heavy"],"public_name":"short_borrow"},{"name":"tengu_v3_reference_crosswalk","method":"GET","path":"/api/v3/reference/crosswalk/{symbol}","group":"v3","description":"IDENTITY CROSSWALK for one symbol — every identifier the security and its issuer carry, which rung matched, and how confident that match is. Returns SECURITY-grain identifiers (CUSIP9, CUSIP8, ISIN, SEDOL, ticker, estimate-vendor ticker) kept deliberately SEPARATE from the ISSUER-grain keys (gvkey, CUSIP6, regulator filer number, entity id), because those identify a company and not a share line; plus the issuer's other listed securities, the dated timeline of every identifier this security has ever been bound to, and the bridge into the private-company graph with that link's confidence grade. Call it to join two data sets that key on different identifiers, to translate a CUSIP-keyed holdings file into tickers, or to find out what a symbol used to be. as_of=YYYY-MM-DD resolves the symbol on the bindings IN FORCE on that date and returns the identifiers in force then, not today's — FB resolves today to an ETF, FB as_of=2020-01-01 to Meta, and as_of_resolution names both holders. A symbol shared by more than one current security is REFUSED with its candidate list rather than guessed; pass prefer_country to choose. A symbol the security master has never held is a 404 unknown_ticker. Coverage is a number in every response: what THIS answer contains, and the corpus census (securities, issuers, identifier bindings and issuers linked to the private graph, measured for the response). Identifier-history depth is uneven by construction — about half of the securities carry a prior ticker — and every source block states its own as-of, its age in days and whether that age is past its expected refresh cadence.","path_params":["symbol"],"query_params":[{"name":"as_of","type":"string","description":"YYYY-MM-DD. Return the identifiers that were in force on that date instead of today's"},{"name":"prefer_country","type":"string","description":"Disambiguation policy for a symbol shared by more than one current security, e.g. USA. Without it a shared symbol is REFUSED with its candidates"},{"name":"include_history","type":"bool","default":true,"description":"Include the dated identifier timeline"},{"name":"include_share_classes","type":"bool","default":true,"description":"Include the issuer's other securities"},{"name":"include_private_graph","type":"bool","default":true,"description":"Include the private-company-graph link"}],"admin":false,"display_name":"Identifier crosswalk","capability_tags":["heavy"],"public_name":"reference_crosswalk"},{"name":"tengu_v3_reference_lookup","method":"GET","path":"/api/v3/reference/lookup","group":"v3","description":"REVERSE IDENTIFIER LOOKUP — give it a CUSIP, ISIN, SEDOL, ticker, estimate-vendor ticker, gvkey, regulator filer number, entity id or private-company-graph id and it returns the security (or, for an ISSUER key, every security under that issuer) plus which rung matched and whether that binding is still current. Exactly one identifier per call. RETIRED identifiers resolve by default — most of the bindings on file are retired, which is precisely why a stale identifier in your own data still lands, and it comes back with the date it was replaced and by what. Issuer keys NEVER nominate one security: an issuer can carry a common line, other share classes and a foreign listing, so all of them are returned and the grain is stated. Use it to turn a CUSIP-keyed custodian file into tickers, to find the ticker behind a regulator filing, or to audit whether an identifier in your own data has gone stale. Rung coverage is measured in every response (coverage.dataset.rung_fill_pct): CUSIP9 and CUSIP8 on every security, the other rungs on fewer.","query_params":[{"name":"cusip","type":"string","description":"9 or 8 characters resolve a SECURITY; 6 characters are an ISSUER key and return every security under it"},{"name":"isin","type":"string"},{"name":"sedol","type":"string"},{"name":"ticker","type":"string"},{"name":"ibtic","type":"string","description":"Estimate-vendor ticker"},{"name":"gvkey","type":"string","description":"ISSUER key"},{"name":"cik","type":"string","description":"Regulator filer number — an ISSUER key"},{"name":"entity_id","type":"string","description":"This API's issuer entity id"},{"name":"private_company_id","type":"string","description":"Private-company-graph id — returns the listed issuer it bridges to, if any"},{"name":"permno","type":"string","description":"research-grade security number (1-7 digits): every link to an issuer with its valid_from/valid_to dates, the link covering today, and that issuer's securities with the linked one flagged; the source's as_of is its newest link date (monthly)"},{"name":"include_retired","type":"bool","default":true,"description":"Also match identifiers that have been RETIRED"}],"param_constraints":[{"exactly_one_of":["cusip","isin","sedol","ticker","ibtic","gvkey","cik","entity_id","private_company_id"]}],"admin":false,"display_name":"Identifier lookup","public_name":"reference_lookup"},{"name":"tengu_v3_reference_history","method":"GET","path":"/api/v3/reference/history/{symbol}","group":"v3","description":"IDENTIFIER HISTORY for one symbol — every identifier this security has ever been bound to, with the dates each binding started and ended, plus the dated events where the ISSUER changed its name, ticker or CUSIP. This is the part of a crosswalk a current-state table cannot give you: it answers 'what was this on 2015-06-30', 'when did this CUSIP change' and 'what was this company called then'. Returns the timeline grouped by identifier rung (each entry with valid_from, valid_thru and whether it is still current), the issuer change events with what changed at each one, and — with as_of — the security that held the symbol on that date and the exact set of identifiers in force then. Use it to back-map a historical holdings file, to audit identifier drift in your own data, or to explain a ticker that no longer exists. STALENESS, stated rather than implied: the issuer change log is a VINTAGE snapshot that lags the live security master (as-of 2026-04-20 when this shipped, 104 days old, newest change event 2026-01-30). Its age in days and its expected cadence are in every response, and any disagreement between it and the live spine is named explicitly rather than blended into one confident answer. Coverage is a number, measured in every response: the identifier bindings on file, how many are retired, and how many securities carry at least one prior ticker.","path_params":["symbol"],"query_params":[{"name":"as_of","type":"string","description":"YYYY-MM-DD — also return the identifiers in force on that date"},{"name":"prefer_country","type":"string","description":"Disambiguation policy for a shared symbol, e.g. USA"},{"name":"include_change_log","type":"bool","default":true,"description":"Include the dated issuer name/ticker/CUSIP change events (a VINTAGE — its age is reported)"}],"admin":false,"display_name":"Identifier history","capability_tags":["heavy"],"public_name":"reference_history"},{"name":"tengu_v3_reference_batch","method":"GET","path":"/api/v3/reference/batch","group":"v3","description":"BATCH CROSSWALK — up to 100 symbols resolved in ONE pass, each returning its current identifiers (CUSIP9, CUSIP8, ISIN, SEDOL, ticker, estimate-vendor ticker), its issuer keys (gvkey, CUSIP6, regulator filer number), which rung matched and its status. This is the endpoint for mapping a whole portfolio or watchlist in a single call rather than N of them. Every symbol comes back with an explicit status — resolved, historical (renamed or delisted; the security and what it trades as now are both returned), ambiguous (shared by more than one current security: the candidates are listed and NO identity is guessed) or unknown (not carried). Symbols beyond the 100 limit come back as explicit over_limit entries, never silently dropped, and the response reports how many of the requested symbols resolved as a number and a percentage (measured 2026-08-02 on a 102-symbol large-cap list: 100 looked up, 99 resolved, 1 historical, 2 over_limit).","query_params":[{"name":"symbols","type":"string","required":true,"description":"Comma-separated symbols, up to 100"},{"name":"prefer_country","type":"string","description":"Disambiguation policy for shared symbols, e.g. USA"}],"admin":false,"display_name":"Crosswalk (batch)","capability_tags":["heavy"],"public_name":"reference_batch"},{"name":"tengu_v3_reference_coverage","method":"GET","path":"/api/v3/reference/coverage","group":"v3","description":"CROSSWALK COVERAGE — what the reference dataset actually contains, measured live and stated as numbers rather than adjectives: securities and issuers carried and how many are still active, identifier bindings held and how many are RETIRED, the percentage of securities carrying each rung, how many issuers bridge into the private-company graph and how those links break down by confidence grade, and how many dated issuer change events are on file. It also NAMES the rungs this crosswalk deliberately does not serve and why — a missing rung is a stated fact here, not a silent gap a customer discovers after integrating. Every source is listed with its own as-of date, its age in days and whether that age is beyond its expected refresh cadence, so a vintage component can never pass as current. Every figure is measured when it is served, never quoted from a past measurement. Call it before you buy, or before you build against it.","admin":false,"display_name":"Crosswalk coverage","capability_tags":["heavy"],"public_name":"reference_coverage"},{"name":"tengu_v3_features_catalogue","method":"GET","path":"/api/v3/features/datasets","group":"v3","description":"FEATURE-STORE CATALOGUE — the derived research panels this platform computes for its own models: what exists, how much of it there is, how far back it goes, and how fresh it actually is. Every entry carries MEASURED coverage (rows, symbols, distinct observation dates, history window) and a measured freshness block. freshness.status is `current` only when the producer is inside twice its own declared cadence AND the data is on its own rhythm, and `archival` when either fails but the dataset is a genuine historical panel — an archival dataset is still readable, EVERY read of it says so, and not_current_reason names the clock that is behind (data_behind_its_own_cadence for a producer that runs over old data). stale_for_its_own_cadence fires when the newest observation (or a panel's newest vintage, freshness.vintage_clock) is more than three of that clock's own typical gaps old — counted in weekdays for a daily panel, so a weekend or holiday is not a missed observation. vintage_column names the per-row vintage a panel carries (ratio_vintage, returns_data_through); coverage.rows_dated_after_today counts rows stamped with a future date and, on a monthly panel, coverage.rows_written_before_month_end the rows written before their month ended (a month in progress); neither is served. Datasets whose producer stopped and which are NOT panels are listed under `withheld` with the measurement that disqualified them and have NO route at all; a dataset MEASURED into that state (not a panel, and its producer stopped or its data behind its own rhythm) carries freshness.status `withheld` and is refused on read; `excluded` lists live datasets deliberately not sold here, with the reason. The response's coverage block gives the measured counts (datasets current, archival, withheld and excluded; rows in total). Call it first: it is the only place the slugs for /api/v3/features/{dataset} are published.","admin":false,"display_name":"Feature store catalogue","capability_tags":["heavy"],"public_name":"features_catalogue"},{"name":"tengu_v3_features_dataset","method":"GET","path":"/api/v3/features/{dataset}","group":"v3","description":"READ ONE DERIVED FEATURE PANEL — the model-ready research features this platform computes for itself: price/return and liquidity features, monthly fundamentals, analyst-estimate dynamics, options and volatility-surface features, insider and institutional-ownership features, news-sentiment features, betas, regime and macro features. Discover the slugs via /api/v3/features/datasets — they are product names, not table names. With ?ticker= you get that symbol's observations newest first; without it you get the LATEST cross-section (every symbol on the most recent observation date), which is bounded by construction rather than by sorting the whole panel. observation_date is the date the row describes; a panel that carries a vintage serves it beside it (ratio_vintage on the monthly fundamentals: when the valuation ratios were published; returns_data_through on the betas: where the return history behind the estimate ends), and rows dated after today, or monthly rows written before their month ended, are not served. Symbols resolve through the shared security resolver first and identity.identity_verified states whether the read was keyed on an authoritative identifier or on the resolved security's symbol; an ambiguous symbol is refused, never guessed. Every response carries the dataset's measured coverage (rows_total, symbols_total, observation_dates, history window) and its freshness, so an empty rows array arrives beside the count of symbols that DO have rows and can never be read as a dead upstream — `result` is the machine-readable outcome (rows, no_rows_for_symbol, no_rows_in_window). An `archival` dataset (producer stopped, or data behind its own rhythm) is served for its history, and every response says so rather than implying currency. An unknown or withheld slug — including one whose measured freshness is `withheld` (404 dataset_withheld, with reason and freshness) — is a 404 and an unreadable store is a 503 — both refunded, because a billed 200 over an empty array is the defect this endpoint exists to remove.","path_params":["dataset"],"query_params":[{"name":"ticker","type":"string","description":"Symbol to read the time series for; omit for the latest cross-section"},{"name":"limit","type":"int","default":500,"min":1,"max":5000},{"name":"since","type":"string","description":"Inclusive lower bound, YYYY-MM-DD"},{"name":"until","type":"string","description":"Inclusive upper bound, YYYY-MM-DD"}],"admin":false,"display_name":"Feature panel","capability_tags":["heavy"],"public_name":"features_dataset"},{"name":"tengu_v3_crypto_market_profile","method":"GET","path":"/api/v3/crypto/market/profile","group":"v3","description":"Call this when the user asks for a coin's price, market cap, rank, supply or all-time high/low, for one coin or up to 50 at once (symbols=BTC,ETH,SOL or ids=). Each coin comes back with its id, name and symbol. Fields and units: current_price, market_cap, fully_diluted_valuation and total_volume (24 h) in vs_currency; market_cap_rank (1 = largest); circulating/total/max_supply in coins; ath and atl in vs_currency with ath_date/atl_date (UTC) and ath_change_percentage/atl_change_percentage (percent from each); price_change_percentage_1h/24h/7d/30d/1y in PERCENT (5.2 = +5.2 %).","query_params":[{"name":"symbols","type":"string","description":"Comma list of ticker symbols, e.g. BTC,ETH (at most 50 with ids)."},{"name":"ids","type":"string","description":"Comma list of exact coin ids, e.g. bitcoin,ethereum."},{"name":"vs_currency","type":"string","default":"usd","description":"Currency every price, market cap and volume is quoted in (usd, eur, btc, eth, ...). Default usd."},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional; these tools only serve crypto (crypto)."}],"admin":false,"param_constraints":[{"at_least_one_of":["symbols","ids"]}],"display_name":"Coin profile","public_name":"crypto_market_profile"},{"name":"tengu_v3_crypto_market_history","method":"GET","path":"/api/v3/crypto/market/history","group":"v3","description":"Call this when the user asks how a coin's price, market cap or volume moved over a year, five years or its whole life: one row per day. Fields and units: rows[].date (UTC day) and t_ms (ms epoch, 00:00 UTC); close, market_cap and volume_24h in vs_currency. Each row's close is the price at 00:00 UTC, i.e. the previous day's close; the last row is the latest price.","query_params":[{"name":"symbol","type":"string","description":"Coin ticker symbol, e.g. BTC. When several coins share a symbol the one with the best market-cap rank is used; symbol_resolution names it and the other candidates. Give symbol or id."},{"name":"id","type":"string","description":"Exact coin id, e.g. bitcoin (as returned in id). Give symbol or id."},{"name":"days","type":"string","enum":["365","1825","max"],"default":"365","description":"How far back: 365 (1 year), 1825 (5 years) or max (since listing)."},{"name":"interval","type":"string","enum":["daily"],"default":"daily","description":"Row interval. daily only."},{"name":"vs_currency","type":"string","default":"usd","description":"Currency every price, market cap and volume is quoted in (usd, eur, btc, eth, ...). Default usd."},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional; these tools only serve crypto (crypto)."}],"admin":false,"param_constraints":[{"exactly_one_of":["symbol","id"]}],"display_name":"Coin price history","public_name":"crypto_market_history"},{"name":"tengu_v3_crypto_market_coin","method":"GET","path":"/api/v3/crypto/market/coin","group":"v3","description":"Call this when the user asks what a coin is, its links, categories, genesis or contract addresses, or wants every market figure for one coin in one answer. Fields and units: data is the coin record: market_data.current_price/market_cap/total_volume are maps of currency -> amount; market_data.price_change_percentage_* are PERCENT; supply fields in coins; dates ISO-8601 UTC.","query_params":[{"name":"symbol","type":"string","description":"Coin ticker symbol, e.g. BTC. When several coins share a symbol the one with the best market-cap rank is used; symbol_resolution names it and the other candidates. Give symbol or id."},{"name":"id","type":"string","description":"Exact coin id, e.g. bitcoin (as returned in id). Give symbol or id."},{"name":"localization","type":"bool","default":false,"description":"Include names and descriptions in every language. Default false."},{"name":"tickers","type":"bool","default":false,"description":"Include exchange tickers (use crypto_market_tickers instead). Default false."},{"name":"market_data","type":"bool","default":true,"description":"Include market data. Default true."},{"name":"community_data","type":"bool","default":false,"description":"Include social statistics. Default false."},{"name":"developer_data","type":"bool","default":false,"description":"Include code repository statistics. Default false."},{"name":"sparkline","type":"bool","default":false,"description":"Include a 7-day hourly price series. Default false."},{"name":"include_categories_details","type":"bool","description":"Include each category's id and name."},{"name":"dex_pair_format","type":"string","enum":["contract_address","symbol"],"description":"How decentralised-exchange pairs are named: contract_address or symbol."},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional; these tools only serve crypto (crypto)."}],"admin":false,"param_constraints":[{"exactly_one_of":["symbol","id"]}],"display_name":"Coin details","public_name":"crypto_market_coin"},{"name":"tengu_v3_crypto_market_chart","method":"GET","path":"/api/v3/crypto/market/chart","group":"v3","description":"Call this when the user wants a coin's recent price, market cap and volume series (e.g. the last 1, 7, 30 or 90 days) to chart or compare. Fields and units: prices, market_caps, total_volumes are [timestamp ms epoch UTC, value in vs_currency]; 1 day = 5-minute points, 2-90 days = hourly, more = daily.","query_params":[{"name":"symbol","type":"string","description":"Coin ticker symbol, e.g. BTC. When several coins share a symbol the one with the best market-cap rank is used; symbol_resolution names it and the other candidates. Give symbol or id."},{"name":"id","type":"string","description":"Exact coin id, e.g. bitcoin (as returned in id). Give symbol or id."},{"name":"days","type":"string","default":"30","description":"Days back: an integer 1-99999, or max. Default 30."},{"name":"interval","type":"string","enum":["daily"],"description":"daily forces one point per day."},{"name":"vs_currency","type":"string","default":"usd","description":"Currency every price, market cap and volume is quoted in (usd, eur, btc, eth, ...). Default usd."},{"name":"precision","type":"string","enum":["full","0","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18"],"description":"Decimal places for prices: 0-18, or full."},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional; these tools only serve crypto (crypto)."}],"admin":false,"param_constraints":[{"exactly_one_of":["symbol","id"]}],"display_name":"Coin chart","public_name":"crypto_market_chart"},{"name":"tengu_v3_crypto_market_chart_range","method":"GET","path":"/api/v3/crypto/market/chart/range","group":"v3","description":"Call this when the user wants a coin's price, market cap and volume between two exact dates. Fields and units: prices, market_caps, total_volumes are [timestamp ms epoch UTC, value in vs_currency]; spans up to 90 days are hourly, longer spans daily.","query_params":[{"name":"symbol","type":"string","description":"Coin ticker symbol, e.g. BTC. When several coins share a symbol the one with the best market-cap rank is used; symbol_resolution names it and the other candidates. Give symbol or id."},{"name":"id","type":"string","description":"Exact coin id, e.g. bitcoin (as returned in id). Give symbol or id."},{"name":"from","type":"int","min":0,"max":4102444800,"required":true,"description":"Start, unix seconds UTC."},{"name":"to","type":"int","min":0,"max":4102444800,"required":true,"description":"End, unix seconds UTC (after from)."},{"name":"interval","type":"string","enum":["daily"],"description":"daily forces one point per day."},{"name":"vs_currency","type":"string","default":"usd","description":"Currency every price, market cap and volume is quoted in (usd, eur, btc, eth, ...). Default usd."},{"name":"precision","type":"string","enum":["full","0","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18"],"description":"Decimal places for prices: 0-18, or full."},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional; these tools only serve crypto (crypto)."}],"admin":false,"param_constraints":[{"exactly_one_of":["symbol","id"]}],"display_name":"Coin chart (date range)","public_name":"crypto_market_chart_range"},{"name":"tengu_v3_crypto_market_ohlc","method":"GET","path":"/api/v3/crypto/market/ohlc","group":"v3","description":"Call this when the user wants a coin's open-high-low-close candles. Fields and units: each row is [timestamp ms epoch UTC of the candle's close, open, high, low, close] in vs_currency; 1-2 days = 30-minute candles, 3-30 days = 4-hour, 31+ days = 4-day (interval=daily gives daily candles).","query_params":[{"name":"symbol","type":"string","description":"Coin ticker symbol, e.g. BTC. When several coins share a symbol the one with the best market-cap rank is used; symbol_resolution names it and the other candidates. Give symbol or id."},{"name":"id","type":"string","description":"Exact coin id, e.g. bitcoin (as returned in id). Give symbol or id."},{"name":"days","type":"string","enum":["1","7","14","30","90","180","365","max"],"default":"30","description":"Days back. Default 30."},{"name":"interval","type":"string","enum":["daily","hourly"],"description":"Force daily or hourly candles."},{"name":"vs_currency","type":"string","default":"usd","description":"Currency every price, market cap and volume is quoted in (usd, eur, btc, eth, ...). Default usd."},{"name":"precision","type":"string","enum":["full","0","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18"],"description":"Decimal places for prices: 0-18, or full."},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional; these tools only serve crypto (crypto)."}],"admin":false,"param_constraints":[{"exactly_one_of":["symbol","id"]}],"display_name":"Coin candles (OHLC)","public_name":"crypto_market_ohlc"},{"name":"tengu_v3_crypto_market_tickers","method":"GET","path":"/api/v3/crypto/market/tickers","group":"v3","description":"Call this when the user asks where a coin trades: its trading pairs on every exchange, with price, 24 h volume, spread and liquidity grade (100 per page). Fields and units: last in the pair's quote currency; volume in base units, 24 h; converted_last and converted_volume in btc/eth/usd; bid_ask_spread_percentage in PERCENT; timestamps ISO-8601 UTC.","query_params":[{"name":"symbol","type":"string","description":"Coin ticker symbol, e.g. BTC. When several coins share a symbol the one with the best market-cap rank is used; symbol_resolution names it and the other candidates. Give symbol or id."},{"name":"id","type":"string","description":"Exact coin id, e.g. bitcoin (as returned in id). Give symbol or id."},{"name":"exchange_ids","type":"string","description":"Only these exchanges (comma list of exchange ids)."},{"name":"include_exchange_logo","type":"bool","description":"Include exchange logos."},{"name":"page","type":"int","default":1,"min":1,"max":1000,"description":"Page number, from 1."},{"name":"order","type":"string","enum":["trust_score_desc","trust_score_asc","volume_desc","volume_asc"],"description":"Sort order. Default trust_score_desc."},{"name":"depth","type":"bool","description":"Include the cost to move the price 2 % up and down."},{"name":"dex_pair_format","type":"string","enum":["contract_address","symbol"],"description":"How decentralised-exchange pairs are named: contract_address or symbol."},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional; these tools only serve crypto (crypto)."}],"admin":false,"param_constraints":[{"exactly_one_of":["symbol","id"]}],"display_name":"Where a coin trades","public_name":"crypto_market_tickers"},{"name":"tengu_v3_crypto_market_on_date","method":"GET","path":"/api/v3/crypto/market/on_date","group":"v3","description":"Call this when the user asks what a coin's price, market cap or volume was on a specific past date. Fields and units: market_data.current_price/market_cap/total_volume are maps of currency -> amount at 00:00 UTC on that date.","query_params":[{"name":"symbol","type":"string","description":"Coin ticker symbol, e.g. BTC. When several coins share a symbol the one with the best market-cap rank is used; symbol_resolution names it and the other candidates. Give symbol or id."},{"name":"id","type":"string","description":"Exact coin id, e.g. bitcoin (as returned in id). Give symbol or id."},{"name":"date","type":"string","required":true,"description":"The date, YYYY-MM-DD (UTC), from 2009-01-03 to today."},{"name":"localization","type":"bool","default":false,"description":"Include names in every language. Default false."},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional; these tools only serve crypto (crypto)."}],"admin":false,"param_constraints":[{"exactly_one_of":["symbol","id"]}],"display_name":"Coin on a date","public_name":"crypto_market_on_date"},{"name":"tengu_v3_crypto_market_contract","method":"GET","path":"/api/v3/crypto/market/contract","group":"v3","description":"Call this when the user gives a token's contract address and chain and wants to know which coin it is and its market data. Fields and units: data is the coin record: market_data maps of currency -> amount, price_change_percentage_* in PERCENT, dates ISO-8601 UTC.","query_params":[{"name":"platform","type":"string","required":true,"description":"Chain (asset platform) id, e.g. ethereum, solana, binance-smart-chain (from crypto_market_asset_platforms)."},{"name":"address","type":"string","required":true,"description":"The token's contract address on that chain."},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional; these tools only serve crypto (crypto)."}],"admin":false,"display_name":"Token by contract","public_name":"crypto_market_contract"},{"name":"tengu_v3_crypto_market_coins","method":"GET","path":"/api/v3/crypto/market/coins","group":"v3","description":"Call this when the user wants a ranked table of coins (by market cap, volume or name), optionally filtered to ids, symbols or a category, with price and percentage changes. Fields and units: current_price, market_cap, total_volume (24 h) in vs_currency; price_change_percentage_* in PERCENT; supply in coins; last_updated ISO-8601 UTC.","query_params":[{"name":"vs_currency","type":"string","default":"usd","description":"Currency every price, market cap and volume is quoted in (usd, eur, btc, eth, ...). Default usd."},{"name":"ids","type":"string","description":"Only these coin ids (comma list)."},{"name":"symbols","type":"string","description":"Only these symbols (comma list)."},{"name":"include_tokens","type":"string","enum":["top","all"],"description":"With symbols: top = the best-ranked coin per symbol, all = every coin."},{"name":"category","type":"string","description":"Only coins in this category id (from crypto_market_categories_list)."},{"name":"order","type":"string","enum":["market_cap_desc","market_cap_asc","volume_desc","volume_asc","id_asc","id_desc"],"default":"market_cap_desc","description":"Sort order. Default market_cap_desc."},{"name":"per_page","type":"int","default":100,"min":1,"max":250,"description":"Rows per page, 1-250."},{"name":"page","type":"int","default":1,"min":1,"max":1000,"description":"Page number, from 1."},{"name":"sparkline","type":"bool","default":false,"description":"Include a 7-day hourly price series. Default false."},{"name":"price_change_percentage","type":"string","description":"Extra change windows, comma list, e.g. 1h,7d,30d. Values: 1h, 24h, 7d, 14d, 30d, 200d, 1y."},{"name":"precision","type":"string","enum":["full","0","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18"],"description":"Decimal places for prices: 0-18, or full."},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional; these tools only serve crypto (crypto)."}],"admin":false,"display_name":"Coin market table","public_name":"crypto_market_coins"},{"name":"tengu_v3_crypto_market_coins_list","method":"GET","path":"/api/v3/crypto/market/coins/list","group":"v3","description":"Call this when you need every coin's id, symbol and name (about 17,000 rows), e.g. to map symbols to ids in bulk. Large: prefer crypto_market_search or a symbol on the other tools. Fields and units: rows of id, symbol, name; with include_platform a map of chain -> contract address.","query_params":[{"name":"include_platform","type":"bool","default":false,"description":"Include each coin's contract addresses. Default false."},{"name":"status","type":"string","enum":["active","inactive"],"description":"Active (default) or delisted coins."},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional; these tools only serve crypto (crypto)."}],"admin":false,"display_name":"All coin ids","public_name":"crypto_market_coins_list"},{"name":"tengu_v3_crypto_market_coins_new","method":"GET","path":"/api/v3/crypto/market/coins/new","group":"v3","description":"Call this when the user asks which coins were listed most recently. Fields and units: activated_at is unix seconds UTC.","query_params":[{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional; these tools only serve crypto (crypto)."}],"admin":false,"display_name":"New coin listings","public_name":"crypto_market_coins_new"},{"name":"tengu_v3_crypto_market_movers","method":"GET","path":"/api/v3/crypto/market/movers","group":"v3","description":"Call this when the user asks which coins rose or fell the most (top gainers and losers) over 1h to 1y, filtered to coins with real trading volume, plus what is trending in searches. Fields and units: usd is the price in USD; usd_24h_vol is USD traded over 24 h; usd_<duration>_change is PERCENT (5.2 = +5.2 %); rows below min_volume_usd are dropped and counted.","query_params":[{"name":"duration","type":"string","enum":["1h","24h","7d","14d","30d","60d","1y"],"default":"24h","description":"Change window. Default 24h."},{"name":"min_volume_usd","type":"float","default":1000000.0,"min":0,"description":"Drop coins that traded less than this many USD in 24 h. Default 1000000."},{"name":"top_coins","type":"string","enum":["300","500","1000","all"],"default":"1000","description":"Rank among the top N coins by market cap. Default 1000."},{"name":"include_trending","type":"bool","default":true,"description":"Also return what is trending in searches. Default true."},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional; these tools only serve crypto (crypto)."}],"admin":false,"display_name":"Crypto gainers & losers","public_name":"crypto_market_movers"},{"name":"tengu_v3_crypto_market_trending","method":"GET","path":"/api/v3/crypto/market/trending","group":"v3","description":"Call this when the user asks what coins, categories or NFTs are trending in searches right now. Fields and units: coins[].item.data.price in USD; price_change_percentage_24h.<currency> in PERCENT; market_cap and total_volume are formatted USD strings.","query_params":[{"name":"show_max","type":"string","description":"Return the longer list for these (comma list). Values: coins, nfts, categories."},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional; these tools only serve crypto (crypto)."}],"admin":false,"display_name":"Crypto trending (searches)","public_name":"crypto_market_trending"},{"name":"tengu_v3_crypto_market_categories","method":"GET","path":"/api/v3/crypto/market/categories","group":"v3","description":"Call this when the user asks how crypto sectors are doing (DeFi, layer 1, memes, AI ...): market cap and 24 h change per category; with category= the top coins inside one category. Fields and units: market_cap and volume_24h in USD; market_cap_change_24h in PERCENT; with category, coin rows as in crypto_market_coins (current_price, market_cap in vs_currency; changes in PERCENT).","query_params":[{"name":"limit","type":"int","default":50,"min":1,"max":250,"description":"How many categories (or coins, with category). Default 50."},{"name":"order","type":"string","enum":["market_cap_desc","market_cap_asc","name_desc","name_asc","market_cap_change_24h_desc","market_cap_change_24h_asc"],"default":"market_cap_desc","description":"Category sort order. Default market_cap_desc."},{"name":"category","type":"string","description":"A category id (from crypto_market_categories_list): list its top coins."},{"name":"vs_currency","type":"string","default":"usd","description":"With category: the currency of the coin rows. Default usd."},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional; these tools only serve crypto (crypto)."}],"admin":false,"display_name":"Crypto sectors","public_name":"crypto_market_categories"},{"name":"tengu_v3_crypto_market_categories_list","method":"GET","path":"/api/v3/crypto/market/categories/list","group":"v3","description":"Call this when you need every category id and name (to pass as category= elsewhere). Fields and units: rows of category_id and name.","query_params":[{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional; these tools only serve crypto (crypto)."}],"admin":false,"display_name":"Crypto sector ids","public_name":"crypto_market_categories_list"},{"name":"tengu_v3_crypto_market_global","method":"GET","path":"/api/v3/crypto/market/global","group":"v3","description":"Call this when the user asks about the whole crypto market: total market cap, 24 h volume and their change, Bitcoin and Ether dominance, and DeFi's share. Fields and units: total_market_cap and total_volume_24h in vs_currency; market_cap_change_percentage_24h_usd and volume_change_percentage_24h in PERCENT; btc_dominance_pct, eth_dominance_pct and defi_dominance_pct are PERCENT of total market cap; defi_market_cap_usd and defi_volume_24h_usd in USD.","query_params":[{"name":"vs_currency","type":"string","default":"usd","description":"Currency of total_market_cap and total_volume_24h. Default usd."},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional; these tools only serve crypto (crypto)."}],"admin":false,"display_name":"Crypto market overview","public_name":"crypto_market_global"},{"name":"tengu_v3_crypto_market_global_chart","method":"GET","path":"/api/v3/crypto/market/global/chart","group":"v3","description":"Call this when the user wants the total crypto market cap and volume over time. Fields and units: market_cap_chart.market_cap and .volume are [timestamp ms epoch UTC, value in vs_currency].","query_params":[{"name":"days","type":"string","enum":["1","7","14","30","90","180","365","max"],"required":true,"description":"Days back."},{"name":"vs_currency","type":"string","default":"usd","description":"Currency of the values. Default usd."},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional; these tools only serve crypto (crypto)."}],"admin":false,"display_name":"Crypto market cap history","public_name":"crypto_market_global_chart"},{"name":"tengu_v3_crypto_market_search","method":"GET","path":"/api/v3/crypto/market/search","group":"v3","description":"Call this to find a coin, exchange, category or NFT by name or symbol when you do not know its id. Fields and units: rows carry id, name, symbol and market_cap_rank.","query_params":[{"name":"query","type":"string","required":true,"description":"Name or symbol to look for."},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional; these tools only serve crypto (crypto)."}],"admin":false,"display_name":"Coin search","public_name":"crypto_market_search"},{"name":"tengu_v3_crypto_market_price","method":"GET","path":"/api/v3/crypto/market/price","group":"v3","description":"Call this when the user only needs the current price of one or more coins (up to 50 symbols or 250 ids), with market cap, 24 h volume and 24 h change. Fields and units: data.<id>.<currency> is the price in that currency; <currency>_market_cap and <currency>_24h_vol in that currency; <currency>_24h_change in PERCENT; last_updated_at unix seconds UTC.","query_params":[{"name":"symbols","type":"string","description":"Comma list of ticker symbols, e.g. BTC,ETH."},{"name":"ids","type":"string","description":"Comma list of exact coin ids."},{"name":"vs_currencies","type":"string","default":"usd","description":"Comma list of currencies. Default usd."},{"name":"include_market_cap","type":"bool","default":true,"description":"Default true."},{"name":"include_24hr_vol","type":"bool","default":true,"description":"Default true."},{"name":"include_24hr_change","type":"bool","default":true,"description":"Default true."},{"name":"include_last_updated_at","type":"bool","default":true,"description":"Default true."},{"name":"precision","type":"string","enum":["full","0","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18"],"description":"Decimal places for prices: 0-18, or full."},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional; these tools only serve crypto (crypto)."}],"admin":false,"param_constraints":[{"at_least_one_of":["symbols","ids"]}],"display_name":"Coin prices","public_name":"crypto_market_price"},{"name":"tengu_v3_crypto_market_exchanges","method":"GET","path":"/api/v3/crypto/market/exchanges","group":"v3","description":"Call this when the user asks which crypto exchanges are the largest or most trusted. Fields and units: trade_volume_24h_btc in BTC over 24 h; trust_score 1-10.","query_params":[{"name":"per_page","type":"int","default":100,"min":1,"max":250,"description":"Rows per page, 1-250."},{"name":"page","type":"int","default":1,"min":1,"max":1000,"description":"Page number, from 1."},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional; these tools only serve crypto (crypto)."}],"admin":false,"display_name":"Crypto exchanges","public_name":"crypto_market_exchanges"},{"name":"tengu_v3_crypto_market_exchanges_list","method":"GET","path":"/api/v3/crypto/market/exchanges/list","group":"v3","description":"Call this when you need every exchange id and name (to pass as id= elsewhere). Fields and units: rows of id and name.","query_params":[{"name":"status","type":"string","enum":["active","inactive"],"description":"Active (default) or closed exchanges."},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional; these tools only serve crypto (crypto)."}],"admin":false,"display_name":"Crypto exchange ids","public_name":"crypto_market_exchanges_list"},{"name":"tengu_v3_crypto_market_exchange","method":"GET","path":"/api/v3/crypto/market/exchange","group":"v3","description":"Call this when the user asks about one exchange: its volume, trust score, country and top pairs. Fields and units: trade_volume_24h_btc in BTC over 24 h; tickers as crypto_market_tickers.","query_params":[{"name":"id","type":"string","required":true,"description":"Exchange id, e.g. binance (from crypto_market_exchanges_list)."},{"name":"dex_pair_format","type":"string","enum":["contract_address","symbol"],"description":"How decentralised-exchange pairs are named: contract_address or symbol."},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional; these tools only serve crypto (crypto)."}],"admin":false,"display_name":"Crypto exchange profile","public_name":"crypto_market_exchange"},{"name":"tengu_v3_crypto_market_exchange_tickers","method":"GET","path":"/api/v3/crypto/market/exchange/tickers","group":"v3","description":"Call this when the user wants every trading pair on one exchange, optionally for given coins (100 per page). Fields and units: last in the pair's quote currency; volume in base units, 24 h; converted_* in btc/eth/usd; bid_ask_spread_percentage in PERCENT.","query_params":[{"name":"id","type":"string","required":true,"description":"Exchange id, e.g. binance (from crypto_market_exchanges_list)."},{"name":"coin_ids","type":"string","description":"Only these coin ids."},{"name":"include_exchange_logo","type":"bool","description":"Include exchange logos."},{"name":"page","type":"int","default":1,"min":1,"max":1000,"description":"Page number, from 1."},{"name":"depth","type":"bool","description":"Include the cost to move the price 2 % up and down."},{"name":"order","type":"string","enum":["trust_score_desc","trust_score_asc","volume_desc","volume_asc","base_target"],"description":"Sort order."},{"name":"dex_pair_format","type":"string","enum":["contract_address","symbol"],"description":"How decentralised-exchange pairs are named: contract_address or symbol."},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional; these tools only serve crypto (crypto)."}],"admin":false,"display_name":"Exchange trading pairs","public_name":"crypto_market_exchange_tickers"},{"name":"tengu_v3_crypto_market_exchange_volume","method":"GET","path":"/api/v3/crypto/market/exchange/volume","group":"v3","description":"Call this when the user asks how an exchange's trading volume changed over time. Fields and units: each row is [timestamp ms epoch UTC, volume in BTC (a decimal string)].","query_params":[{"name":"id","type":"string","required":true,"description":"Exchange id, e.g. binance (from crypto_market_exchanges_list)."},{"name":"days","type":"string","enum":["1","7","14","30","90","180","365"],"required":true,"description":"Days back."},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional; these tools only serve crypto (crypto)."}],"admin":false,"display_name":"Exchange volume history","public_name":"crypto_market_exchange_volume"},{"name":"tengu_v3_crypto_market_derivatives_exchanges","method":"GET","path":"/api/v3/crypto/market/derivatives/exchanges","group":"v3","description":"Call this when the user asks which derivatives exchanges have the most open interest or volume. Fields and units: open_interest_btc and trade_volume_24h_btc in BTC; counts of perpetual and futures pairs.","query_params":[{"name":"order","type":"string","enum":["name_asc","name_desc","open_interest_btc_asc","open_interest_btc_desc","trade_volume_24h_btc_asc","trade_volume_24h_btc_desc"],"description":"Sort order."},{"name":"per_page","type":"int","default":100,"min":1,"max":250,"description":"Rows per page, 1-250."},{"name":"page","type":"int","default":1,"min":1,"max":1000,"description":"Page number, from 1."},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional; these tools only serve crypto (crypto)."}],"admin":false,"display_name":"Crypto derivatives venues","public_name":"crypto_market_derivatives_exchanges"},{"name":"tengu_v3_crypto_market_derivatives_exchanges_list","method":"GET","path":"/api/v3/crypto/market/derivatives/exchanges/list","group":"v3","description":"Call this when you need every derivatives exchange id and name. Fields and units: rows of id and name.","query_params":[{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional; these tools only serve crypto (crypto)."}],"admin":false,"display_name":"Derivatives venue ids","public_name":"crypto_market_derivatives_exchanges_list"},{"name":"tengu_v3_crypto_market_derivatives_exchange","method":"GET","path":"/api/v3/crypto/market/derivatives/exchange","group":"v3","description":"Call this when the user asks about one derivatives exchange: open interest, volume and, with include_tickers, its contracts. Fields and units: open_interest_btc and trade_volume_24h_btc in BTC; tickers[].funding_rate in PERCENT per funding interval; open_interest_usd in USD.","query_params":[{"name":"id","type":"string","required":true,"description":"Derivatives exchange id (from crypto_market_derivatives_exchanges_list)."},{"name":"include_tickers","type":"string","enum":["all","unexpired"],"description":"Include contracts: all, or unexpired only."},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional; these tools only serve crypto (crypto)."}],"admin":false,"display_name":"Derivatives venue profile","public_name":"crypto_market_derivatives_exchange"},{"name":"tengu_v3_crypto_market_asset_platforms","method":"GET","path":"/api/v3/crypto/market/asset_platforms","group":"v3","description":"Call this when you need every blockchain (asset platform) id, e.g. to look a token up by contract address. Fields and units: rows of id, chain_identifier, name.","query_params":[{"name":"filter","type":"string","enum":["nft"],"description":"nft = only chains that support NFTs."},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional; these tools only serve crypto (crypto)."}],"admin":false,"display_name":"Blockchain ids","public_name":"crypto_market_asset_platforms"},{"name":"tengu_v3_crypto_market_exchange_rates","method":"GET","path":"/api/v3/crypto/market/exchange_rates","group":"v3","description":"Call this when the user wants Bitcoin's exchange rate against fiat currencies, commodities and other coins. Fields and units: rates.<code>.value is units of that asset per 1 BTC.","query_params":[{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional; these tools only serve crypto (crypto)."}],"admin":false,"display_name":"Bitcoin exchange rates","public_name":"crypto_market_exchange_rates"},{"name":"tengu_v3_crypto_market_treasuries","method":"GET","path":"/api/v3/crypto/market/treasuries","group":"v3","description":"Call this when the user asks which public companies hold Bitcoin or Ether and how much. Fields and units: total_holdings in coins; total_value_usd, total_entry_value_usd and total_current_value_usd in USD; percentage_of_total_supply and market_cap_dominance in PERCENT.","query_params":[{"name":"coin","type":"string","enum":["bitcoin","ethereum"],"default":"bitcoin","description":"bitcoin or ethereum. Default bitcoin."},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional; these tools only serve crypto (crypto)."}],"admin":false,"display_name":"Public company crypto holdings","public_name":"crypto_market_treasuries"},{"name":"tengu_v3_crypto_market_onchain_trending_pools","method":"GET","path":"/api/v3/crypto/market/onchain/trending_pools","group":"v3","description":"Call this when the user asks which decentralised-exchange pools are trending on a chain. Fields and units: attributes.*_usd in USD; price_change_percentage.* in PERCENT; volume_usd.* in USD per window; transactions.* are counts.","query_params":[{"name":"network","type":"string","required":true,"description":"Blockchain network id, e.g. eth, solana, base, bsc, arbitrum."},{"name":"include","type":"string","description":"Related records to include (comma list). Values: base_token, quote_token, dex, network."},{"name":"page","type":"int","default":1,"min":1,"max":10,"description":"Page, 1-10."},{"name":"duration","type":"string","enum":["5m","1h","6h","24h"],"description":"Trending window. Default 24h."},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional; these tools only serve crypto (crypto)."}],"admin":false,"display_name":"Trending DEX pools","public_name":"crypto_market_onchain_trending_pools"},{"name":"tengu_v3_crypto_market_onchain_token_price","method":"GET","path":"/api/v3/crypto/market/onchain/token_price","group":"v3","description":"Call this when the user wants the on-chain USD price of tokens by contract address (up to 30 on one chain). Fields and units: token_prices.<address> in USD; market_cap_usd, h24_volume_usd and total_reserve_in_usd in USD; h24_price_change_percentage in PERCENT.","query_params":[{"name":"network","type":"string","required":true,"description":"Blockchain network id, e.g. eth, solana, base, bsc, arbitrum."},{"name":"addresses","type":"string","required":true,"description":"Comma list of up to 30 contract addresses."},{"name":"include_market_cap","type":"bool","description":"Include market cap."},{"name":"mcap_fdv_fallback","type":"bool","description":"Use fully diluted valuation when market cap is unknown."},{"name":"include_24hr_vol","type":"bool","description":"Include 24 h volume."},{"name":"include_24hr_price_change","type":"bool","description":"Include 24 h change."},{"name":"include_total_reserve_in_usd","type":"bool","description":"Include pool reserves."},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional; these tools only serve crypto (crypto)."}],"admin":false,"display_name":"On-chain token prices","public_name":"crypto_market_onchain_token_price"},{"name":"tengu_v3_crypto_market_onchain_token","method":"GET","path":"/api/v3/crypto/market/onchain/token","group":"v3","description":"Call this when the user asks about a token on a decentralised exchange: its price, liquidity, volume and top pools. Fields and units: attributes.price_usd, fdv_usd, market_cap_usd, total_reserve_in_usd in USD; volume_usd.* in USD per window.","query_params":[{"name":"network","type":"string","required":true,"description":"Blockchain network id, e.g. eth, solana, base, bsc, arbitrum."},{"name":"address","type":"string","required":true,"description":"Contract address on that network (0x... or a base58 mint)."},{"name":"include","type":"string","enum":["top_pools"],"description":"top_pools = include its largest pools."},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional; these tools only serve crypto (crypto)."}],"admin":false,"display_name":"On-chain token","public_name":"crypto_market_onchain_token"},{"name":"tengu_v3_crypto_market_onchain_pool","method":"GET","path":"/api/v3/crypto/market/onchain/pool","group":"v3","description":"Call this when the user asks about one decentralised-exchange pool: its prices, liquidity, volume and trades. Fields and units: attributes.*_usd in USD; price_change_percentage.* in PERCENT; volume_usd.* in USD per window; transactions.* are counts.","query_params":[{"name":"network","type":"string","required":true,"description":"Blockchain network id, e.g. eth, solana, base, bsc, arbitrum."},{"name":"address","type":"string","required":true,"description":"Contract address on that network (0x... or a base58 mint)."},{"name":"include","type":"string","description":"Related records to include (comma list). Values: base_token, quote_token, dex."},{"name":"asset_class","type":"string","enum":["crypto"],"description":"Optional; these tools only serve crypto (crypto)."}],"admin":false,"display_name":"DEX pool details","public_name":"crypto_market_onchain_pool"},{"name":"tengu_copilot_score_ticker","method":"GET","path":"/api/v1/copilot/score/{ticker}","group":"copilot","description":"Full per-ticker quant analysis. CALL THIS when the user asks about any specific stock (e.g. 'should I buy NVDA', 'what do you think of TSLA'). Returns an ORDERING, not a forecast: blended_score, rank, decile and percentile in the scored book (which includes funds and ADRs the API does not serve), served_rank / served_decile / served_percentile among the equities the API serves, the voter breakdown (every voter that scored, of the 19-slot ensemble, with the weight it was blended with: a voter the voter policy disables shows weight 0 and status disabled_at_blend; the contributions sum to blended_score when attribution.reproduces_blended_score is true, and when it is false no contributor is named), voters_bullish / voters_bearish, tier, regime and a self-contained narrative. expected_return_pct and the interval are null (magnitudes_withheld) while the live measurement does not support them. No position size is served: suggested_position_pct is always null (sizing_withheld). model_track_record quotes no performance figure; the record is tengu_copilot_track_record. Use the narrative as a quotable summary; use the structured fields for follow-up questions. NAMESPACE: this model's universe is US EQUITIES. Nine tickers (BTC ETH LINK LTC COMP ARB NEAR APT ATOM) are ALSO crypto symbols; for those the response carries a `ticker_collision` block stating the score describes the US-listed EQUITY. If the user means the CRYPTO asset pass asset_class=crypto, which 404s (no crypto model serves this route). For a ranked crypto sleeve (liquid-book scan, scored ordering, top-N) call GET /api/crypto/sitting — that is DATA, signal_quality_mode=ordering_only, not a forecast. The full liquid book is GET /api/crypto/universe. For overnight movers / watchlist DATA call GET /api/crypto/overnight (X-API-Key) — a SLICE of that universe, data/context, not a score. For a ranked US-equity sleeve (full-book scan, attached factors, top-N) call GET /api/equity/sitting — that is DATA, not a score, and do_not_place_from_mover_rank stays true. NEVER present an equity score as a crypto view.","path_params":["ticker"],"query_params":[{"name":"asset_class","type":"string","default":"equity","enum":["equity","crypto"],"description":"equity (default) | crypto. crypto fails closed with 404: no crypto model serves this route — never a wrong-asset answer."}],"admin":false,"display_name":"Quant score","response_schema":{"$defs":{"VoterContribution":{"properties":{"voter":{"title":"Voter","type":"string"},"score":{"description":"Voter score in [-1, +1]","title":"Score","type":"number"},"weight":{"description":"The weight this voter's score was BLENDED with: the regime weight times the voter policy's scale, 0.0 for a voter the policy disables. When attribution.reproduces_blended_score is false the policy could not be applied and this is the nominal weight, which may not be what blended. Until 2026-09-29 it was always the nominal weight.","title":"Weight","type":"number"},"contribution":{"description":"score × weight. Sums to blended_score when attribution.reproduces_blended_score is true; when it is false, do not read it as the score's decomposition.","title":"Contribution","type":"number"},"interpretation":{"description":"One-line plain English","title":"Interpretation","type":"string"},"nominal_weight":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"description":"The regime weight before the voter policy (DEFAULT_BASELINE in the normal regime).","title":"Nominal Weight"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"active | scaled (the policy cuts its weight) | disabled_at_blend (score recorded, weight 0) | shadow (weight 0 by design, pending promotion) | unverified (the voter policy was not applied here, so its blend weight is unknown; attribution.weights_basis says why).","title":"Status"}},"required":["voter","score","weight","contribution","interpretation"],"title":"VoterContribution","type":"object"}},"properties":{"ticker":{"title":"Ticker","type":"string"},"as_of_ts":{"title":"As Of Ts","type":"string"},"knowledge_ts":{"title":"Knowledge Ts","type":"string"},"blended_score":{"description":"In [-1, +1]; >0 = bullish","title":"Blended Score","type":"number"},"decile":{"description":"1-10, 10=top decile","title":"Decile","type":"integer"},"decile_label":{"title":"Decile Label","type":"string"},"rank":{"title":"Rank","type":"integer"},"conviction":{"title":"Conviction","type":"number"},"voter_coverage":{"title":"Voter Coverage","type":"number"},"voters_supporting":{"description":"Voters (blend weight > 0) whose score favours the side in voters_relative_to by more than 0.05: the bullish ones for a long, the bearish ones for a short. When attribution.reproduces_blended_score is false the blend weights are unknown and every voter with a nominal weight counts.","title":"Voters Supporting","type":"integer"},"voters_against":{"description":"Voters (blend weight > 0) whose score opposes that side by more than 0.05.","title":"Voters Against","type":"integer"},"voters_bullish":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"description":"Voters (blend weight > 0) with score > +0.05, whatever the side (nominal weight when attribution.reproduces_blended_score is false).","title":"Voters Bullish"},"voters_bearish":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"description":"Voters (blend weight > 0) with score < -0.05.","title":"Voters Bearish"},"voters_relative_to":{"default":"long","description":"The side voters_supporting / voters_against are counted for: 'short' on a short list, else 'long'. They were bullish/bearish counts on every list until 2026-09-29, so a short pick read '3 supporting, 7 against'.","title":"Voters Relative To","type":"string"},"percentile":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"description":"Cross-sectional percentile of `rank` in the scored book, 0-100, 100 = best: 100*(N-rank)/(N-1) with N the book's size, the same number /universe, the v2 multi-horizon batch and /intel/ml_prediction serve. The book includes the funds and ADRs FIRM excludes from serving; served_percentile ranks within the served equities. Null when the book's size cannot be established. It was the decile midpoint until 2026-09-29. An ORDERING statement, served even when the magnitudes are withheld.","title":"Percentile"},"served_rank":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"description":"Rank among the equities this route serves (the book minus the rows book_guard excludes), 1 = best.","title":"Served Rank"},"served_decile":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"description":"Decile of served_rank among the served equities, 10 = best (the book's own formula).","title":"Served Decile"},"served_percentile":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"description":"Percentile of served_rank among the served equities, 100 = best.","title":"Served Percentile"},"served_universe_size":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"description":"How many equities the served ranking holds.","title":"Served Universe Size"},"attribution":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"description":"Whether voter_breakdown's contributions sum to blended_score (reproduces_blended_score), the weights they use and the voter policy applied at blend time (disabled voters, weight scales).","title":"Attribution"},"sizing_withheld":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"description":"FIRM serves no position size: why suggested_position_pct is always null.","title":"Sizing Withheld"},"expected_return_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Expected Return Pct"},"interval_lo_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Interval Lo Pct"},"interval_hi_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Interval Hi Pct"},"interval_half_width_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Interval Half Width Pct"},"interval_method":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Interval Method"},"tier":{"title":"Tier","type":"string"},"regime":{"title":"Regime","type":"string"},"suggested_position_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"description":"ALWAYS null: FIRM serves no position size (the no-size contract; sizing_withheld says why). The key is kept so a consumer reads a refusal, not a missing field.","title":"Suggested Position Pct"},"magnitudes_withheld":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"description":"Present ONLY when magnitude fields were deliberately withheld. Says which fields and why, so a consumer can distinguish 'we refuse to assert this' from 'the data is missing'.","title":"Magnitudes Withheld"},"voter_breakdown":{"items":{"$ref":"#/$defs/VoterContribution"},"title":"Voter Breakdown","type":"array"},"narrative":{"title":"Narrative","type":"string"},"model_track_record":{"additionalProperties":true,"title":"Model Track Record","type":"object"},"adv_dollars":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"description":"30-day average daily dollar volume from the liquidity_adv sidecar; null when the sidecar has no row for this name","title":"Adv Dollars"},"in_earnings_blackout":{"anyOf":[{"type":"boolean"},{"type":"null"}],"default":null,"description":"True when today is within ±2 trading days of the expected earnings release (annotation only — blackout names are NEVER excluded from picks); null when the earnings_blackout sidecar is unavailable OR has no row for this name (unknown ≠ 'not near earnings')","title":"In Earnings Blackout"},"signal":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"description":"What this ranking can honestly claim. Carries the ORDERING horizon (20d — the horizon the models are trained at), the measured live IC at that horizon, and two SEPARATE answers.\n\n`direction` — which way the number points: aligned | inverted | no_measurable_edge | contradicted | unmeasured. `contradicted` means the headline IC disagrees with the statistics computed from the same rows in the same run (its own tier decomposition, or the realised decile spread) and therefore describes no ordering at all.\n\n`point_estimate_supported` — whether that number may be RELIED ON. BRANCH ON THIS BOOLEAN. It is False whenever any entry appears in `support_blockers`, each of which names its own reason: the measurement is not trustworthy, the estimator is not a within-tier cross-sectional IC, there are too few independent entry dates for the horizon, or the number contradicts its own decomposition.\n\nThe two are separate because a number can point somewhere and still not be usable, and collapsing them is what let a single magnitude comparison decide a customer-facing claim.\n\n`measured_n_resolved` is a ROW COUNT, not independent observations — intraday snapshots on the same date resolve to identical returns (~9x replication). Use `independent_entry_dates`.\n\n`expected_return_pct` is blended_score*100 (predict_pipeline.py:602, 'crude pct mapping'), a monotone rescaling of the rank score and NOT a calibrated forecast.","title":"Signal"},"point_estimate":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"description":"Honest definition of expected_return_pct.","title":"Point Estimate"},"ticker_collision":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"description":"Present ONLY when this bare ticker is also a well-known crypto symbol (BTC/ETH/LINK/LTC/COMP/ARB/NEAR/APT/ATOM). Says explicitly that the score describes the US-listed EQUITY, and how to ask for the crypto asset. Absent for every other name, so existing consumers are byte-identical.","title":"Ticker Collision"},"data_freshness":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"description":"How old the prediction book behind this response is, graded at request time. `data_as_of` is the max as_of_ts of the rows actually served (the DATA's time, never the time the response was rendered or the frame was cached); `data_age_hours` / `data_age_days` its age now; `sessions_behind` the NYSE sessions opened since the book's session. `is_stale` is true when that exceeds `max_sessions_behind` (2), or the age cannot be established, or the stamp is in the future; `stale_reason` names the dates. A stale book is still SERVED, with this disclosure and a narrative that leads with it. Set on /score; list responses carry it once at the top level.","title":"Data Freshness"}},"required":["ticker","as_of_ts","knowledge_ts","blended_score","decile","decile_label","rank","conviction","voter_coverage","voters_supporting","voters_against","tier","regime","voter_breakdown","narrative","model_track_record"],"title":"ScoreResponse","type":"object"},"public_name":"copilot_score_ticker"},{"name":"tengu_copilot_top_picks","method":"GET","path":"/api/v1/copilot/top-picks","group":"copilot","description":"Today's top N picks (long or short side). CALL THIS when the user asks 'what should I buy', 'give me trade ideas', 'top picks today', 'daily briefing', or similar list-of-ideas queries. Each pick comes with the same analysis as score_ticker (score, ordering, voter breakdown, narrative); voters_supporting / voters_against count toward the requested side (the bearish voters support a short; voters_relative_to says which). FIRM serves no position size.","query_params":[{"name":"side","type":"string","default":"long","enum":["long","short"]},{"name":"n","type":"int","default":5,"min":1,"max":20},{"name":"min_adv_dollars","type":"float","min":0,"description":"ADV liquidity floor in dollars/day. Default: 5,000,000 for longs / 10,000,000 for shorts (borrow needed). 0 disables the filter."}],"admin":false,"display_name":"Today's picks","response_schema":{"$defs":{"ScoreResponse":{"properties":{"ticker":{"title":"Ticker","type":"string"},"as_of_ts":{"title":"As Of Ts","type":"string"},"knowledge_ts":{"title":"Knowledge Ts","type":"string"},"blended_score":{"description":"In [-1, +1]; >0 = bullish","title":"Blended Score","type":"number"},"decile":{"description":"1-10, 10=top decile","title":"Decile","type":"integer"},"decile_label":{"title":"Decile Label","type":"string"},"rank":{"title":"Rank","type":"integer"},"conviction":{"title":"Conviction","type":"number"},"voter_coverage":{"title":"Voter Coverage","type":"number"},"voters_supporting":{"description":"Voters (blend weight > 0) whose score favours the side in voters_relative_to by more than 0.05: the bullish ones for a long, the bearish ones for a short. When attribution.reproduces_blended_score is false the blend weights are unknown and every voter with a nominal weight counts.","title":"Voters Supporting","type":"integer"},"voters_against":{"description":"Voters (blend weight > 0) whose score opposes that side by more than 0.05.","title":"Voters Against","type":"integer"},"voters_bullish":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"description":"Voters (blend weight > 0) with score > +0.05, whatever the side (nominal weight when attribution.reproduces_blended_score is false).","title":"Voters Bullish"},"voters_bearish":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"description":"Voters (blend weight > 0) with score < -0.05.","title":"Voters Bearish"},"voters_relative_to":{"default":"long","description":"The side voters_supporting / voters_against are counted for: 'short' on a short list, else 'long'. They were bullish/bearish counts on every list until 2026-09-29, so a short pick read '3 supporting, 7 against'.","title":"Voters Relative To","type":"string"},"percentile":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"description":"Cross-sectional percentile of `rank` in the scored book, 0-100, 100 = best: 100*(N-rank)/(N-1) with N the book's size, the same number /universe, the v2 multi-horizon batch and /intel/ml_prediction serve. The book includes the funds and ADRs FIRM excludes from serving; served_percentile ranks within the served equities. Null when the book's size cannot be established. It was the decile midpoint until 2026-09-29. An ORDERING statement, served even when the magnitudes are withheld.","title":"Percentile"},"served_rank":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"description":"Rank among the equities this route serves (the book minus the rows book_guard excludes), 1 = best.","title":"Served Rank"},"served_decile":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"description":"Decile of served_rank among the served equities, 10 = best (the book's own formula).","title":"Served Decile"},"served_percentile":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"description":"Percentile of served_rank among the served equities, 100 = best.","title":"Served Percentile"},"served_universe_size":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"description":"How many equities the served ranking holds.","title":"Served Universe Size"},"attribution":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"description":"Whether voter_breakdown's contributions sum to blended_score (reproduces_blended_score), the weights they use and the voter policy applied at blend time (disabled voters, weight scales).","title":"Attribution"},"sizing_withheld":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"description":"FIRM serves no position size: why suggested_position_pct is always null.","title":"Sizing Withheld"},"expected_return_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Expected Return Pct"},"interval_lo_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Interval Lo Pct"},"interval_hi_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Interval Hi Pct"},"interval_half_width_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Interval Half Width Pct"},"interval_method":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Interval Method"},"tier":{"title":"Tier","type":"string"},"regime":{"title":"Regime","type":"string"},"suggested_position_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"description":"ALWAYS null: FIRM serves no position size (the no-size contract; sizing_withheld says why). The key is kept so a consumer reads a refusal, not a missing field.","title":"Suggested Position Pct"},"magnitudes_withheld":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"description":"Present ONLY when magnitude fields were deliberately withheld. Says which fields and why, so a consumer can distinguish 'we refuse to assert this' from 'the data is missing'.","title":"Magnitudes Withheld"},"voter_breakdown":{"items":{"$ref":"#/$defs/VoterContribution"},"title":"Voter Breakdown","type":"array"},"narrative":{"title":"Narrative","type":"string"},"model_track_record":{"additionalProperties":true,"title":"Model Track Record","type":"object"},"adv_dollars":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"description":"30-day average daily dollar volume from the liquidity_adv sidecar; null when the sidecar has no row for this name","title":"Adv Dollars"},"in_earnings_blackout":{"anyOf":[{"type":"boolean"},{"type":"null"}],"default":null,"description":"True when today is within ±2 trading days of the expected earnings release (annotation only — blackout names are NEVER excluded from picks); null when the earnings_blackout sidecar is unavailable OR has no row for this name (unknown ≠ 'not near earnings')","title":"In Earnings Blackout"},"signal":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"description":"What this ranking can honestly claim. Carries the ORDERING horizon (20d — the horizon the models are trained at), the measured live IC at that horizon, and two SEPARATE answers.\n\n`direction` — which way the number points: aligned | inverted | no_measurable_edge | contradicted | unmeasured. `contradicted` means the headline IC disagrees with the statistics computed from the same rows in the same run (its own tier decomposition, or the realised decile spread) and therefore describes no ordering at all.\n\n`point_estimate_supported` — whether that number may be RELIED ON. BRANCH ON THIS BOOLEAN. It is False whenever any entry appears in `support_blockers`, each of which names its own reason: the measurement is not trustworthy, the estimator is not a within-tier cross-sectional IC, there are too few independent entry dates for the horizon, or the number contradicts its own decomposition.\n\nThe two are separate because a number can point somewhere and still not be usable, and collapsing them is what let a single magnitude comparison decide a customer-facing claim.\n\n`measured_n_resolved` is a ROW COUNT, not independent observations — intraday snapshots on the same date resolve to identical returns (~9x replication). Use `independent_entry_dates`.\n\n`expected_return_pct` is blended_score*100 (predict_pipeline.py:602, 'crude pct mapping'), a monotone rescaling of the rank score and NOT a calibrated forecast.","title":"Signal"},"point_estimate":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"description":"Honest definition of expected_return_pct.","title":"Point Estimate"},"ticker_collision":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"description":"Present ONLY when this bare ticker is also a well-known crypto symbol (BTC/ETH/LINK/LTC/COMP/ARB/NEAR/APT/ATOM). Says explicitly that the score describes the US-listed EQUITY, and how to ask for the crypto asset. Absent for every other name, so existing consumers are byte-identical.","title":"Ticker Collision"},"data_freshness":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"description":"How old the prediction book behind this response is, graded at request time. `data_as_of` is the max as_of_ts of the rows actually served (the DATA's time, never the time the response was rendered or the frame was cached); `data_age_hours` / `data_age_days` its age now; `sessions_behind` the NYSE sessions opened since the book's session. `is_stale` is true when that exceeds `max_sessions_behind` (2), or the age cannot be established, or the stamp is in the future; `stale_reason` names the dates. A stale book is still SERVED, with this disclosure and a narrative that leads with it. Set on /score; list responses carry it once at the top level.","title":"Data Freshness"}},"required":["ticker","as_of_ts","knowledge_ts","blended_score","decile","decile_label","rank","conviction","voter_coverage","voters_supporting","voters_against","tier","regime","voter_breakdown","narrative","model_track_record"],"title":"ScoreResponse","type":"object"},"VoterContribution":{"properties":{"voter":{"title":"Voter","type":"string"},"score":{"description":"Voter score in [-1, +1]","title":"Score","type":"number"},"weight":{"description":"The weight this voter's score was BLENDED with: the regime weight times the voter policy's scale, 0.0 for a voter the policy disables. When attribution.reproduces_blended_score is false the policy could not be applied and this is the nominal weight, which may not be what blended. Until 2026-09-29 it was always the nominal weight.","title":"Weight","type":"number"},"contribution":{"description":"score × weight. Sums to blended_score when attribution.reproduces_blended_score is true; when it is false, do not read it as the score's decomposition.","title":"Contribution","type":"number"},"interpretation":{"description":"One-line plain English","title":"Interpretation","type":"string"},"nominal_weight":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"description":"The regime weight before the voter policy (DEFAULT_BASELINE in the normal regime).","title":"Nominal Weight"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"active | scaled (the policy cuts its weight) | disabled_at_blend (score recorded, weight 0) | shadow (weight 0 by design, pending promotion) | unverified (the voter policy was not applied here, so its blend weight is unknown; attribution.weights_basis says why).","title":"Status"}},"required":["voter","score","weight","contribution","interpretation"],"title":"VoterContribution","type":"object"}},"properties":{"as_of_ts":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The served prediction frame's real data timestamp (max as_of_ts of the snapshot), NOT the wall time the response was rendered. Null when the frame carries no parseable as_of_ts — never now().","title":"As Of Ts"},"side":{"title":"Side","type":"string"},"regime":{"title":"Regime","type":"string"},"n_returned":{"title":"N Returned","type":"integer"},"picks":{"items":{"$ref":"#/$defs/ScoreResponse"},"title":"Picks","type":"array"},"narrative":{"title":"Narrative","type":"string"},"n_filtered_illiquid":{"default":0,"description":"Names with KNOWN ADV below the liquidity threshold, excluded from the ranked universe. Non-zero means the scan was liquidity-gated, not truncated silently.","title":"N Filtered Illiquid","type":"integer"},"n_filtered_unknown_adv":{"default":0,"description":"Names excluded because the ADV sidecar has NO row for them (unknown liquidity ≠ illiquid — reported separately so sidecar coverage gaps are visible)","title":"N Filtered Unknown Adv","type":"integer"},"snapshot_age_s":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"description":"Seconds since the served prediction snapshot was LOADED into this process (the SWR cache's frame age) — NOT the age of the data. Grows without bound if background refreshes keep failing. The data's age is data_freshness.data_age_hours.","title":"Snapshot Age S"},"snapshot_stale":{"default":false,"description":"True when the served snapshot must not be presented as current, for EITHER reason: its DATA is more than 2 NYSE sessions old (data_freshness.is_stale — a frozen book reloaded seconds ago is still stale), or every in-process refresh has failed for 4h. Served anyway with this warning rather than 503ing. Widened on 2026-09-24: it used to be the second clause only, so a ten-day-old book read false.","title":"Snapshot Stale","type":"boolean"},"data_freshness":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"description":"How old the prediction book behind this response is, graded at request time. `data_as_of` is the max as_of_ts of the rows actually served (the DATA's time, never the time the response was rendered or the frame was cached); `data_age_hours` / `data_age_days` its age now; `sessions_behind` the NYSE sessions opened since the book's session. `is_stale` is true when that exceeds `max_sessions_behind` (2), or the age cannot be established, or the stamp is in the future; `stale_reason` names the dates. A stale book is still SERVED, with this disclosure and a narrative that leads with it.","title":"Data Freshness"},"book_guard":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"description":"Rows removed from this ranking before the response was built, and why. `excluded_by_reason` counts them: non_equity_constant_ml_score = a fund or ADR by the security master's security class (about half such rows also carry the model's no-feature constant score, but the rule is the class); quarantined:<code> = on the served-book quarantine list. `verified` false means a source could not be loaded, and ranking routes then refuse with 503 (error upstream_unavailable, error_code book_guard_unavailable) rather than rank rows nobody checked. rank/decile are the book's own values and are NOT re-ranked after exclusion.","title":"Book Guard"},"liquidity_filter":{"default":"applied","description":"'applied' | 'disabled' (min_adv_dollars=0) | 'unavailable' (liquidity sidecar missing or covering too little of the universe — picks served unfiltered)","title":"Liquidity Filter","type":"string"},"min_adv_dollars":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"description":"Effective ADV threshold in dollars/day used for this response (default: 5M long / 10M short — shorts need borrow)","title":"Min Adv Dollars"}},"required":["side","regime","n_returned","picks","narrative"],"title":"TopPicksResponse","type":"object"},"public_name":"copilot_top_picks"},{"name":"tengu_copilot_universe","method":"GET","path":"/api/v1/copilot/universe","group":"copilot","description":"Every served equity in one call (limit=0 = all of them; the book scores more, and funds, ADRs and quarantined rows are excluded, see book_guard), ranked: blended_score, rank / decile / percentile in the scored book, and served_rank / served_decile / served_percentile among the served equities. Pass tickers=AAPL,NVDA,… to rank a specific basket; omit it to screen the universe (limit/min_decile/side). FIRM serves no position size: suggested_position_pct and normalized_weight are null on every row, with sizing_withheld saying why; normalize and max_weight are accepted and size nothing.","query_params":[{"name":"side","type":"string","default":"long","enum":["long","short"]},{"name":"tickers","type":"string","description":"CSV holdings basket, e.g. AAPL,NVDA,GM"},{"name":"limit","type":"int","default":0,"min":0,"max":20000},{"name":"min_decile","type":"int","default":1,"min":1,"max":10},{"name":"normalize","type":"bool","default":true,"description":"Accepted for compatibility; normalized_weight is always null"},{"name":"max_weight","type":"float","default":0.15,"description":"Accepted for compatibility; no weight is computed from it"}],"admin":false,"capability_tags":["heavy"],"public_name":"copilot_universe"},{"name":"tengu_copilot_macro_regime","method":"GET","path":"/api/v1/copilot/macro-regime","group":"copilot","description":"Current macro regime (read off the prediction book) and the live measured IC. The static table of per-regime historical figures is withheld as the current edge (expected_ic, expected_sharpe, model_strength null) and served labelled as prior_*. CALL THIS when the user asks about market conditions, regime, 'is it a good time to invest', or how confident the model is right now.","admin":false,"display_name":"Market regime","capability_tags":["heavy"],"response_schema":{"properties":{"as_of_ts":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"As Of Ts"},"regime":{"title":"Regime","type":"string"},"regime_label":{"title":"Regime Label","type":"string"},"model_strength":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"WITHHELD (null) since 2026-09-24: the static table's strength label for this regime, which read as the edge right now. The same label is prior_model_strength; the live state is live_ic.state. See static_priors_withheld.","title":"Model Strength"},"expected_ic":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"description":"WITHHELD (null) since 2026-09-24: the static out-of-sample-panel IC for this regime, never re-measured, which read as the current edge. The same figure is prior_ic; the live measurement is live_ic. See static_priors_withheld.","title":"Expected Ic"},"expected_sharpe":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"description":"WITHHELD (null) since 2026-09-24: the static OOS top-decile Sharpe for this regime, now prior_sharpe. There is no live measurement of it.","title":"Expected Sharpe"},"static_priors_withheld":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"description":"Why expected_ic, expected_sharpe and model_strength are null: fields, reason ('static_prior'), detail and use_instead.","title":"Static Priors Withheld"},"prior_basis":{"default":"static_prior","description":"What the prior_* fields are: a static table this endpoint shipped with, never re-measured.","title":"Prior Basis","type":"string"},"prior_ic":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"description":"STATIC PRIOR: the out-of-sample-panel IC for this regime from the table this endpoint shipped with. Never re-measured, not the current edge. Null for a regime the table does not cover.","title":"Prior Ic"},"prior_sharpe":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"description":"STATIC PRIOR: OOS top-decile Sharpe for this regime, from the same table; null when not covered.","title":"Prior Sharpe"},"prior_model_strength":{"default":"unknown","description":"STATIC PRIOR: the table's strength label for this regime; 'unknown' when not covered.","title":"Prior Model Strength","type":"string"},"live_ic":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"description":"The live measured IC at the ordering horizon — the same measurement /score's signal block carries: measured_ic, horizon_days, direction, support_blockers, and state: 'aligned' or 'inverted' (a reading FIRM stands behind), 'no_measurable_edge', 'not_established' (support blockers stop FIRM standing behind it) or 'unmeasured'.","title":"Live Ic"},"narrative":{"title":"Narrative","type":"string"},"data_freshness":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"description":"How old the prediction book behind this response is, graded at request time. `data_as_of` is the max as_of_ts of the rows actually served (the DATA's time, never the time the response was rendered or the frame was cached); `data_age_hours` / `data_age_days` its age now; `sessions_behind` the NYSE sessions opened since the book's session. `is_stale` is true when that exceeds `max_sessions_behind` (2), or the age cannot be established, or the stamp is in the future; `stale_reason` names the dates. A stale book is still SERVED, with this disclosure and a narrative that leads with it.","title":"Data Freshness"}},"required":["regime","regime_label","narrative"],"title":"RegimeResponse","type":"object"},"public_name":"copilot_macro_regime"},{"name":"tengu_copilot_portfolio","method":"POST","path":"/api/v1/copilot/portfolio","group":"copilot","description":"Score a list of user-held tickers and report factor tilts and top strengths/weaknesses. regime_appropriateness is withheld (null): it restated a static per-regime table, served labelled as prior_regime_fit. CALL THIS when the user shares their holdings (broker-connected or pasted), or asks 'how is my portfolio', 'what should I trim/add', 'where am I overweight'. Body is JSON: {holdings: [{ticker: 'AAPL', weight_pct: 0.04}, ...]}.","body_schema":{"required":["holdings"],"type":"object","properties":{"holdings":{"items":{"required":["ticker","weight_pct"],"type":"object","properties":{"ticker":{"type":"string"},"weight_pct":{"type":"number","description":"FRACTION of NAV — 0.04 = 4%"}},"additionalProperties":false},"minItems":1,"type":"array"}},"additionalProperties":false},"admin":false,"display_name":"Portfolio review","public_name":"copilot_portfolio"},{"name":"tengu_copilot_top_picks_portfolio_aware","method":"POST","path":"/api/v1/copilot/top-picks-portfolio-aware","group":"copilot","description":"Portfolio-aware 'what should I buy' picks. Call this instead of tengu_copilot_top_picks when you have the user's holdings. Differs from top_picks in three ways: (1) skips any ticker the user already holds, (2) penalises candidates highly correlated with existing holdings (cosine ≥ 0.7 + sector match), (3) boosts candidates that reduce saturated factor tilts or fill under-represented sectors. No position size is served: each pick's suggested_size_pct_unconstrained and suggested_size_pct_with_portfolio are always null, with a magnitudes_withheld block saying why, and the narrative gives no NAV figure: null is a refusal to size, never a size of 0%. Body: {holdings:[{ticker,weight_pct},...], side:'long'|'short', n, diversification_weight (0-1, default 0.5)}. Each pick has an inclusion_reason field with a 1-line plain-English rationale for WHY this pick fits THIS user's portfolio — quote it.","body_schema":{"required":["holdings"],"type":"object","properties":{"holdings":{"items":{"required":["ticker","weight_pct"],"type":"object","properties":{"ticker":{"type":"string"},"weight_pct":{"type":"number","description":"FRACTION of NAV — 0.04 = 4%"}},"additionalProperties":false},"minItems":1,"type":"array"},"side":{"default":"long","pattern":"^(long|short)$","type":"string","enum":["long","short"]},"n":{"default":5,"maximum":20,"minimum":1,"type":"integer"},"diversification_weight":{"default":0.5,"maximum":1.0,"minimum":0.0,"type":"number"}},"additionalProperties":false},"admin":false,"display_name":"Picks for your portfolio","public_name":"copilot_top_picks_portfolio_aware"},{"name":"tengu_copilot_portfolio_impact","method":"POST","path":"/api/v1/copilot/portfolio-impact","group":"copilot","description":"Portfolio-aware verdict on a candidate ticker. Call this when you have the user's holdings and they ask about a specific ticker. Returns the candidate's full standalone analysis PLUS pre/post sector + voter-tilt comparison, concentration warnings, correlated holdings already in the portfolio, and the portfolio context in sizing_rationale. No position size is served: suggested_size_pct_unconstrained and suggested_size_pct_with_portfolio are always null, with a magnitudes_withheld block saying why: null is a refusal to size, never a size of 0%. Body is JSON: {holdings:[{ticker, weight_pct},...], candidate_ticker, candidate_weight_pct (default 0.04)}. The narrative field is the quotable spine — quote it or rewrite in your voice.","body_schema":{"required":["holdings","candidate_ticker"],"type":"object","properties":{"holdings":{"items":{"required":["ticker","weight_pct"],"type":"object","properties":{"ticker":{"type":"string"},"weight_pct":{"type":"number","description":"FRACTION of NAV — 0.04 = 4%"}},"additionalProperties":false},"minItems":1,"type":"array"},"candidate_ticker":{"maxLength":10,"minLength":1,"type":"string"},"candidate_weight_pct":{"default":0.04,"type":"number","description":"fraction of NAV"}},"additionalProperties":false},"admin":false,"display_name":"Portfolio impact","public_name":"copilot_portfolio_impact"},{"name":"tengu_copilot_track_record","method":"GET","path":"/api/v1/copilot/track-record","group":"copilot","description":"Out-of-sample model performance — Sharpe, IC, factor-decomp alpha, DSR confidence, PBO, SPA. CALL THIS when the user asks 'how do I know this works', 'what's your track record', 'is this real alpha vs factor exposure'. evidence_status says which research reports were read: a report produced from the retired four/five-voter panel is quarantined and not read, and its figures are null (never 0). as_of_ts is the newest report's own time. Quote strict_oos_dsr_confidence (a probability) and pbo beside any raw Sharpe. Realised conformal coverage is never served (unavailable pending migration, as tengu_v3_intel_model_calibration says). The strict-OOS DSR confidence is deflated against the registered trial count, a FLOOR on trials run, so it is an upper bound; dsr_n_trials and the DSR fields are null (never 0) when the research loop's trial corpus is unavailable, and dsr_registry says which corpus publication was used. Each report family carries its own as_of and a stale flag in `report_freshness`; a report with no generation time of its own is stale (provenance unknown_generation_time).","admin":false,"display_name":"Track record","response_schema":{"properties":{"as_of_ts":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The newest generation time among the reports actually read (report_freshness has each one's). Null when none was read. It was the request time until 2026-09-29.","title":"As Of Ts"},"evidence_status":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"description":"{report family: loaded | quarantined_partial_voter_evidence | unavailable}. A quarantined family was produced from a retired four/five-voter panel and is not evidence about the current ensemble, so it is not read.","title":"Evidence Status"},"headline_ic_1m":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Headline Ic 1M"},"headline_decile_spread_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"description":"Mean top-minus-bottom decile return, in percent, over headline_decile_spread_horizon.","title":"Headline Decile Spread Pct"},"headline_decile_spread_horizon":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The holding period headline_decile_spread_pct is measured over ('1m': monthly rebalance).","title":"Headline Decile Spread Horizon"},"headline_sharpe_gross":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Headline Sharpe Gross"},"headline_sharpe_net":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Headline Sharpe Net"},"strict_oos_ic_1m":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Strict Oos Ic 1M"},"strict_oos_sharpe":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Strict Oos Sharpe"},"strict_oos_dsr_confidence":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"description":"DSR confidence in [0, 1]: the probability the observed strict-OOS Sharpe exceeds the trial-count-adjusted null max. A PROBABILITY, not a Sharpe. Above 0.95 = significant; below 0.50 = likely one of many random trials. The same value as strict_oos_sharpe_deflated.","title":"Strict Oos Dsr Confidence"},"strict_oos_sharpe_deflated":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"description":"DEPRECATED NAME, same value as strict_oos_dsr_confidence: a probability in [0, 1], NOT a Sharpe value. Deflated alpha in Sharpe units is `strict_oos_deflated_alpha_sr`.","title":"Strict Oos Sharpe Deflated"},"strict_oos_dsr_p_value":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"description":"P-value (1 − DSR confidence): probability the observed Sharpe is spurious under the multi-trial null. p < 0.05 is publication-grade significance; p < 0.01 is high confidence.","title":"Strict Oos Dsr P Value"},"strict_oos_deflated_alpha_sr":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"description":"Deflated alpha in Sharpe units: (observed_SR − expected_max_null_SR) on the input scale. Positive means observed Sharpe exceeds the trial-adjusted null; negative means it falls short. This is the true 'skill alpha' after multi-comparison adjustment.","title":"Strict Oos Deflated Alpha Sr"},"strict_oos_dsr_expected_max_sr":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"description":"Expected maximum Sharpe under the null hypothesis across the registered trial count. Reported in the same units as strict_oos_sharpe (annualized).","title":"Strict Oos Dsr Expected Max Sr"},"dsr_n_trials":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"description":"Number of strategy trials registered in the DSR registry. The Sharpe deflation is computed against this count (more trials = stronger deflation). It is a FLOOR on the trials actually run, so the DSR confidence is an upper bound. null (never 0) when the research loop's trial corpus is unavailable; the deflation fields are then null too.","title":"Dsr N Trials"},"dsr_registry":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"description":"What dsr_n_trials is: n_trials_total, source, the corpus publication it came from (rows, published_at, etag), count_is_lower_bound and submitted_at_basis. The same block /api/v3/validation/* serves.","title":"Dsr Registry"},"strict_oos_n_months":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Strict Oos N Months"},"conformal_coverage_realized":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"description":"ALWAYS null: the legacy coverage measurement was taken at an incompatible horizon and is not bound to the released model (the quarantine /api/v3/intel/model_calibration applies). See conformal_coverage_status.","title":"Conformal Coverage Realized"},"conformal_coverage_status":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"unavailable_migration_pending, with conformal_coverage_reason.","title":"Conformal Coverage Status"},"conformal_coverage_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Conformal Coverage Reason"},"conformal_coverage_target":{"default":0.9,"title":"Conformal Coverage Target","type":"number"},"factor_alpha_annualised":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Factor Alpha Annualised"},"factor_alpha_t_stat":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Factor Alpha T Stat"},"cpcv_median_oos_sharpe":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"description":"Combinatorial Purged Cross-Validation: median Sharpe across all (purged + embargoed) OOS paths. More robust than walk-forward because every observation is held out at least once. Should be in the same ballpark as strict_oos_sharpe; if much lower, the headline Sharpe is overfit to fold boundaries.","title":"Cpcv Median Oos Sharpe"},"cpcv_pct_positive_paths":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"description":"Percentage of CPCV OOS paths with positive Sharpe. Above 60% indicates broad-based OOS robustness. Below 50% means the strategy is right-tailed-only (works on average but fails most paths).","title":"Cpcv Pct Positive Paths"},"cpcv_n_paths":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Cpcv N Paths"},"cpcv_ci95_lower":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"description":"Lower bound of 95% Student-t confidence interval on the MEAN OOS Sharpe across CPCV paths. With small n_paths the interval is wide and surfacing it matters: a +0.44 median Sharpe with CI [0.15, 0.71] is meaningfully different from one with CI [0.40, 0.48].","title":"Cpcv Ci95 Lower"},"cpcv_ci95_upper":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Cpcv Ci95 Upper"},"pbo":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"description":"Probability of Backtest Overfitting (Bailey/LdP 2014). 0 = no overfit risk, 1 = certain overfit. Values < 0.5 are considered acceptable; > 0.5 means the headline backtest will likely fail OOS. Computed against synthetic strategy perturbations as a conservative proxy.","title":"Pbo"},"pbo_ci_lower":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Pbo Ci Lower"},"pbo_ci_upper":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Pbo Ci Upper"},"information_ratio":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"description":"Information Ratio = (mean excess return vs market) / tracking error, annualised. Most institutional LPs lead with IR over Sharpe — IR rewards consistent outperformance of a passive benchmark.","title":"Information Ratio"},"tracking_error":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"description":"Annualised standard deviation of (strategy − benchmark) returns. High tracking error means the strategy looks very different from the benchmark; low TE means it largely tracks. LPs use this to size the active risk budget.","title":"Tracking Error"},"beta_market":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"description":"Strategy beta to the market portfolio. ~0 means market-neutral; ~1 means moves with the market. Computed via OLS on monthly returns.","title":"Beta Market"},"alpha_annual_vs_market":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"title":"Alpha Annual Vs Market"},"spa_p_value":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"description":"Hansen's SPA-consistent p-value: probability that the BEST of N candidate strategy variants beats the benchmark by chance, accounting for the multiple-comparison problem of testing all N at once. p < 0.05 = LP-grade significance; p < 0.01 = high confidence. Complementary to DSR: DSR adjusts a single Sharpe for trial count, SPA adjusts a comparison across K candidates.","title":"Spa P Value"},"spa_n_strategies":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Spa N Strategies"},"rc_p_value":{"anyOf":[{"type":"number"},{"type":"null"}],"default":null,"description":"White's Reality Check p-value (less powerful but simpler than SPA-c). Reported alongside SPA-c for cross-reference; SPA-c is preferred.","title":"Rc P Value"},"n_months_full_panel":{"title":"N Months Full Panel","type":"integer"},"narrative":{"title":"Narrative","type":"string"},"report_freshness":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"description":"Per-report-family freshness: {family: {as_of, as_of_field, provenance, report_age_hours: float|null, max_age_hours, stale: bool}}. Age comes ONLY from the report's own generation timestamp; a report without one has provenance='unknown_generation_time' and stale=true (a file's upload time is not its generation time). stale = older than max_age_hours (14 days for these research reports). Families here may be image-baked fallbacks — this block exposes that honestly instead of shipping May's stats as current.","title":"Report Freshness"}},"required":["n_months_full_panel","narrative"],"title":"TrackRecordResponse","type":"object"},"public_name":"copilot_track_record"},{"name":"tengu_copilot_signal_health","method":"GET","path":"/api/v1/copilot/signal-health","group":"copilot","description":"CONTRACT C2 — is the alpha signal fit to trade, and do we actually know? CALL THIS BEFORE acting on /top-picks or /score. Returns a closed-vocabulary `status` (healthy | degraded | do_not_trade | unknown), a `tradeable` boolean to branch on, `decile_convention` (10_is_best), the per-horizon live IC, and prose guidance. Fail CLOSED on anything other than `healthy` — treat it as an empty candidate list. `unknown` is a real verdict, not a placeholder: it means no BELIEVABLE current measurement exists, which carries the same instruction as red. The contract checks whether the measurement is trustworthy, not merely recent — a drift job that re-stamps a frozen input publishes today's date over old numbers, and this refuses to grade that as fresh.","admin":false,"public_name":"copilot_signal_health"},{"name":"tengu_copilot_live_ic_drift","method":"GET","path":"/api/v1/copilot/live-ic-drift","group":"copilot","description":"Live IC drift status — comparison of realised live IC vs training-time IC. The canonical alpha-decay early warning. It reads the SAME measurement tengu_copilot_signal_health grades (measurement_source says which was read): each horizon names its estimator (mean_daily_within_tier_ic when published), with xs_ic_t_stat and xs_n_dates; n_resolved is a row count, not independent observations, and the decile means are tail-sensitive raw means. CALL THIS when the user asks 'is the model still working?', 'any drift?', 'should we trust today's predictions?'. Returns ic_ratio (live / training) per horizon, drift status (green / yellow / red), and a plain-English narrative. Sub-second; refreshed daily after the close. ic_ratio < 0 = sign flip (scores anti-predictive); ic_ratio < 0.3 = severe decay; ic_ratio > 1.0 = model outperforming training expectation. `as_of` is when the snapshot was generated; `stale: true` means it is over 3 days old or undated, so the verdict describes the past, not today.","admin":false,"display_name":"Signal quality (live)","public_name":"copilot_live_ic_drift"},{"name":"tengu_copilot_voter_ic_drift","method":"GET","path":"/api/v1/copilot/voter-ic-drift","group":"copilot","description":"Per-voter IC drift breakdown — pinpoints WHICH of the measured voters in the ensemble is decaying. The blended-IC drift tool tells you IF the ensemble is decaying; this tells you WHICH voter. CALL THIS when the user asks 'which voter is the problem?', 'why did the model decay?', 'should we re-weight?'. Critically distinguishes 'data_silent' (voter source offline → not the voter's fault) from 'real decay' (voter producing scores that no longer predict). Returns per-voter live IC, an empirical baseline IC (historical voter scores), ic_ratio, drift severity, current weight, and operator-suggested weight delta (capped ±0.05 absolute per cycle). ic_ratio is null when there is no baseline, or when the baseline is negative (drift_severity baseline_not_positive: no edge to decay from); the producer's verdict is kept as as_built. n_real_decay counts the severe and sign-flip voters the narrative names. `as_of` is the newest prediction the snapshot measured (`built_at` is when it was built); `stale: true` (top level and on every voter) means `as_of` is over 80 hours old (a weekend plus the build lag) or undated. Across a holiday weekend the last snapshot reads stale until the next build although nothing newer can exist yet. `stale_at_build` is the producer's own verdict.","admin":false,"display_name":"Signal quality (per voter)","public_name":"copilot_voter_ic_drift"},{"name":"tengu_copilot_ticker_transparency","method":"GET","path":"/api/v3/copilot/ticker_transparency/{ticker}","group":"copilot","description":"ML-transparency aggregation for one ticker — collapses 5 individual tools (ml_drivers, ml_prediction, model_calibration, voter_ic_drift, voter_coverage) into a SINGLE call. Use when a verdict needs the model-transparency layer ('why is the model saying this?'). Saves 4 HTTP calls per verdict. Returns a 5-layer payload + `degraded:bool` + `missing_layers:[...]` so partial failures still produce usable output; a layer that answers 200 with ok:false is missing (missing_reasons `swallowed_200:...`). A layer whose own data_freshness says is_stale (the prediction book behind ml_prediction and voter_coverage) is in stale_layers and sets degraded. `as_of` is the core layer's DATA time (null when it states none), `rendered_at` the response time. Cache TTL 60s. Pass `cache_max_age_s=0` to bypass cache.","path_params":["ticker"],"query_params":[{"name":"cache_max_age_s","type":"float","min":0,"max":3600}],"admin":false,"capability_tags":["copilot_aggregation_v1"],"public_name":"copilot_ticker_transparency"},{"name":"tengu_copilot_ticker_smartmoney","method":"GET","path":"/api/v3/copilot/ticker_smartmoney/{ticker}","group":"copilot","description":"Smart-money aggregation for one ticker — collapses 7 individual tools (sec13f_changes, institutional_ownership, insider_trades, options_flow, darkpool, max_pain, gex) into ONE call. Use when a verdict needs positioning context ('who's accumulating?', 'what is the options market saying?'). Saves 6 HTTP calls per verdict. Same `degraded` / `missing_layers` contract as ticker_transparency; a layer whose vendor refused (missing_reasons `vendor_error_<status>`) is missing, and a layer whose SOURCE is stale sets `degraded` with missing_reasons `stale:<age>` while its data stays in `layers`. options_flow read live with no recent alert for a quiet ticker is not stale-sourced and does not set `degraded`; its body still carries is_stale / age_hours. Cache TTL 180s — positioning doesn't tick at chat cadence.","path_params":["ticker"],"query_params":[{"name":"cache_max_age_s","type":"float","min":0,"max":3600}],"admin":false,"capability_tags":["copilot_aggregation_v1"],"public_name":"copilot_ticker_smartmoney"},{"name":"tengu_copilot_ticker_full","method":"GET","path":"/api/v3/copilot/ticker_full/{ticker}","group":"copilot","description":"OMNIBUS aggregation for one ticker — the single-call single-stock verdict path. Pulls BOTH the 5-layer transparency cluster AND the 7-layer smartmoney cluster in ONE call (up to 12 underlying tools in parallel, server-side). Replaces a 24-72 call fan-out with a single call. Use for 'should I buy X?' / 'what do you think of Y?' / 'verdict on Z' shapes. `include_smartmoney` and `include_transparency` flags let comparison views skip clusters they don't need. `degraded` is true when a layer failed, its vendor refused, or its source is stale (not a quiet ticker's options-flow alert list; a stale prediction book counts); `missing_reasons` says which. `as_of` is the core layer's DATA time, `rendered_at` the response time. Cache TTL 60s. Pass `cache_max_age_s=0` to bypass cache.","path_params":["ticker"],"query_params":[{"name":"include_smartmoney","type":"bool","default":true},{"name":"include_transparency","type":"bool","default":true},{"name":"candidate_weight_pct","type":"float","min":0,"max":100,"description":"Echoed back unchanged; nothing is computed from it yet, so no unit is applied. Note the POST portfolio tools take candidate_weight_pct as a FRACTION of NAV (0.04 = 4%)."},{"name":"cache_max_age_s","type":"float","min":0,"max":3600}],"admin":false,"capability_tags":["copilot_aggregation_v1"],"public_name":"copilot_ticker_full"},{"name":"tengu_copilot_capital_allocation_full","method":"POST","path":"/api/v3/copilot/capital_allocation_full","group":"copilot","description":"Capital-allocation answer in one call: the decision framework, the risk-free rate, the macro regime and the top picks (portfolio-aware when has_portfolio is true and holdings are sent), each pick with its model attribution and voter coverage. Use it for 'what should I buy with $X', 'top picks for my book' or 'best opportunities right now'. Answers are cached for 5 minutes; cache_max_age_s=0 forces a fresh one.","body_schema":{"type":"object","properties":{"has_portfolio":{"default":false,"type":"boolean"},"holdings":{"items":{"additionalProperties":true,"type":"object"},"type":["array","null"]},"side":{"default":"long","type":"string","enum":["long","short"]},"n":{"default":5,"maximum":20,"minimum":1,"type":"integer"}},"additionalProperties":false,"required":[]},"query_params":[{"name":"cache_max_age_s","type":"float","min":0,"max":3600}],"admin":false,"capability_tags":["copilot_aggregation_v1"],"public_name":"copilot_capital_allocation_full"},{"name":"tengu_copilot_comparison_full","method":"POST","path":"/api/v3/copilot/comparison_full","group":"copilot","description":"Side-by-side comparison of 2-6 tickers in one call, for 'X vs Y', 'should I buy NVDA or AMD' or 'compare these three names': for each ticker the model prediction, its drivers, voter coverage, analyst consensus and insider trades, keyed per ticker (layers.ml_prediction__NVDA, layers.ml_prediction__AMD). Answers are cached for 2 minutes; cache_max_age_s=0 forces a fresh one.","body_schema":{"required":["tickers"],"type":"object","properties":{"tickers":{"items":{"type":"string"},"maxItems":6,"minItems":2,"type":"array"},"holdings":{"items":{"additionalProperties":true,"type":"object"},"type":["array","null"],"description":"Reserved: not used by any computation; the response reports only holdings_provided."}},"additionalProperties":false},"query_params":[{"name":"cache_max_age_s","type":"float","min":0,"max":3600}],"admin":false,"capability_tags":["copilot_aggregation_v1"],"public_name":"copilot_comparison_full"},{"name":"tengu_copilot_briefing_overnight","method":"POST","path":"/api/v3/copilot/briefing_overnight","group":"copilot","description":"Pre-market overnight briefing for a list of holdings and a watchlist (up to 50 each): overnight news and the next earnings date per ticker, plus today's earnings calendar, the macro regime and today's top picks, and risk_flags for holdings (e.g. 'NVDA reports in 18h', 'high overnight news volume on AAPL'). Answers for the same tickers are cached for 4 hours; cache_max_age_s=0 forces a fresh one. user_id is optional and is echoed back only to its own caller.","body_schema":{"type":"object","properties":{"user_id":{"type":["string","null"]},"holdings":{"items":{"type":"string"},"maxItems":50,"type":"array"},"watchlist":{"items":{"type":"string"},"maxItems":50,"type":"array"},"timezone":{"type":["string","null"],"default":"America/New_York"}},"additionalProperties":false,"required":[]},"query_params":[{"name":"cache_max_age_s","type":"float","min":0,"max":14400}],"admin":false,"capability_tags":["copilot_aggregation_v1","proactive_intelligence_v1","heavy"],"public_name":"copilot_briefing_overnight"},{"name":"tengu_copilot_decision_track","method":"POST","path":"/api/v3/copilot/decision_track","group":"copilot","description":"RECORD A DECISION the user has acted on. Pass the ticker, side (long/short), entry_price + entry_ts (optional — defaults to now-UTC), weight_pct, a one-sentence thesis_summary, and the FULL original verdict snapshot (typically the response from tengu_copilot_ticker_full). Returns a decision_id you store. Idempotent on (ticker, side, entry_ts, thesis_score). Kept for 90 days. tengu_copilot_decision_review re-fetches the verdict later with that id and reports how the thesis has held up since entry.","body_schema":{"required":["ticker","side"],"type":"object","properties":{"ticker":{"type":"string"},"side":{"pattern":"^(long|short)$","type":"string","enum":["long","short"]},"entry_price":{"exclusiveMinimum":0,"type":["number","null"]},"entry_ts":{"type":["string","null"]},"weight_pct":{"maximum":100,"minimum":0,"type":["number","null"]},"thesis_summary":{"maxLength":2000,"type":["string","null"]},"original_verdict_snapshot":{"additionalProperties":true,"type":["object","null"]}},"additionalProperties":false},"admin":false,"capability_tags":["decision_followup_v1","preview"],"public_name":"copilot_decision_track"},{"name":"tengu_copilot_decision_review","method":"GET","path":"/api/v3/copilot/decision_review/{decision_id}","group":"copilot","description":"REVIEW A TRACKED DECISION. Pass the decision_id returned by decision_track. The API re-fetches the same verdict shape (ticker_full) and computes a structured DELTA against the original snapshot. Returns thesis_status in {intact, weakening, broken, n/a} based on the score delta projected into the user's side direction. Includes a narrative the chat can render verbatim. decision_id is dec_ plus 16 lowercase hex characters (anything else is a 422). A key reads only the decisions it tracked: another key's id answers 404, the same as an id that expired (90-day TTL) or was never recorded. Use this for the 'your AAPL position you opened Tuesday is up X% — thesis is tracking' callback shape.","path_params":["decision_id"],"admin":false,"capability_tags":["decision_followup_v1","preview"],"public_name":"copilot_decision_review"}],"tool_count":407,"deprecated_count":64,"pending_count":41,"cached":false,"naming":{"public_name":"The tool's name over MCP (tools/list, tools/call) and its OpenAPI operationId. Call tools by this name.","name":"The stable manifest id. tools/call accepts it too."},"include_deprecated":false,"include_pending":false,"admin_included":false}