Financial intelligence platform API โ Trump Truth Social, X/Twitter financial news, macro economics, US equities, options & institutional flow, earnings, China A-shares / Stock Connect and the Daily Brief. 42 endpoints in 12 groups.
Every endpoint except this page and /api/openapi.json requires an API key, sent in one of two headers:
| Header | Example |
|---|---|
| X-API-Key | X-API-Key: avk_your_key_here |
| Authorization | Authorization: Bearer avk_your_key_here |
export KEY=avk_your_key_here
curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/posts?limit=5"
curl -H "Authorization: Bearer $KEY" "https://news.all-vista.org/api/posts?limit=5"
401 Unauthorized with a JSON body {"error":"Unauthorized","hint":โฆ,"docs":"/api/docs"}.Two classes of key exist. A server key (avs_โฆ, issued for back-office integrations) is not rate limited. The public key (avk_โฆ, the one the website itself uses) is limited per client IP over a rolling 5-minute window:
| Scope | Limit / 5 min | Applies to |
|---|---|---|
| api | 1500 per IP | Every endpoint that is not LLM-backed |
| llm | 60 per IP, 600 across all IPs | POST /api/analyze, POST /api/x-analyze, POST /api/x-analyze-batch, POST /api/x-digest, POST /api/bwe-analyze, POST /api/bwe-digest, GET /api/macro-analysis, POST /api/stock-analysis, POST /api/flow/recap |
429 with a Retry-After header and {"error":"Too many requests","retry_after_seconds":N}. Cached hits count too, so batch reads where you can.The same reference is published as OpenAPI 3.1 at /api/openapi.json (no key required). Point Swagger UI, Redoc, Postman, an SDK generator or an LLM agent at it:
curl -s https://news.all-vista.org/api/openapi.json | jq '.paths | keys'
npx @redocly/cli preview-docs https://news.all-vista.org/api/openapi.json
2026.09.07. LLM-backed operations are tagged x-llm: true; routes that set a cache header carry x-cache.Truth Social posts with AI market-impact analysis, aggregate impact stats and intraday price reactions.
Newest first. Each post carries _analysis (the cached AnalysisResult from POST /api/analyze, or null). Media-only posts, posts that are only a URL, and posts the analysis flagged as empty are hidden from the feed.
| Name | Type | Description |
|---|---|---|
| page | integeroptionaldefault 11โโฆ | Page number (1-based); values below 1 are clamped to 1, and 0 or a non-numeric value falls back to 1. |
| limit | integeroptionaldefault 201โ100 | Posts per page, clamped to 1โ100; 0 or a non-numeric value falls back to 20. |
| q | stringoptional | Case-insensitive substring search over the post text and the linked card's title and description. |
| from | stringoptional | Date range start, YYYY-MM-DD (inclusive, from 00:00 UTC). |
| to | stringoptional | Date range end, YYYY-MM-DD (inclusive, through 23:59:59.999 UTC). |
PostPage{
"posts": [
{
"id": "114090816417968547",
"created_at": "2025-02-28T14:23:00.000Z",
"content": "<p>post HTML content</p>",
"language": "en",
"url": "https://truthsocial.com/@realDonaldTrump/...",
"account": { "username": "realDonaldTrump", "followers_count": 9200000, "verified": true, ... },
"media_attachments": [ { "id": "...", "type": "image", "url": "/media/....png", "preview_url": "...", ... } ],
"card": { "url": "...", "title": "...", "description": "...", "image": "...", "provider_name": "..." }, // or null
"replies_count": 1200,
"reblogs_count": 2100,
"favourites_count": 8500,
"_analysis": { ... } // AnalysisResult if available, else null
}
],
"total": 842,
"page": 1,
"limit": 20,
"hasMore": true
}
page is clamped to at least 1 and limit to 1โ100 (the response echoes the effective values); the page window is (page - 1) * limit to page * limit over the filtered list.curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/posts?q=tariff&from=2025-03-01&limit=5"
curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/posts?page=2&limit=50"
Returns the cached AnalysisResult when one exists (with X-AI-Provider: cache); otherwise runs the LLM on the post text, its linked article excerpt and attached images, stores the result, and returns it with X-AI-Provider / X-AI-Model headers.
| Name | Type | Description |
|---|---|---|
| post_id | stringrequired | Truth Social post ID. |
AnalysisResult{
"topic": "tariff", // macro|energy|tariff|social_media|legal|election|other
"impact_direction": "bearish", // bullish|bearish|neutral|uncertain
"impact_magnitude": 2, // 0-3
"confidence": 0.85, // 0.0-1.0
"suggested_symbols": ["SPY", "QQQ", "EEM"],
"headline": "...", // Chinese headline
"headline_en": "...", // English headline
"translation": "...", // Chinese translation of post
"rationale": "...", // Chinese summary
"rationale_en": "...", // English summary
"key_points": ["..."], // Chinese key points
"key_points_en": ["..."], // English key points
"market_impact": "...", // Chinese detailed analysis
"market_impact_en": "...", // English detailed analysis
"risk_factors": ["..."], // Chinese risk factors
"risk_factors_en": ["..."], // English risk factors
"time_horizon": "short_term" // short_term|medium_term|long_term|unclear
}
| Code | Meaning |
|---|---|
| 202 | Analysis already in progress for this post โ retry later |
| 400 | Missing post_id |
| 404 | Post not found |
| 500 | Analysis failed (all LLM providers errored) |
202 if analysis is already in progress for this post.X-AI-Provider: cache and X-AI-Model: cached; fresh results carry the provider and model that produced them.X-AI-Provider / X-AI-Model headers.curl -H "X-API-Key: $KEY" -X POST https://news.all-vista.org/api/analyze -H "Content-Type: application/json" -d '{"post_id": "114090816417968547"}'
Exactly one of ids or summary is required; ids takes precedence when both are present. Each post maps to the first US session it could move (posts at or after 16:00 ET, or on a weekend / holiday, roll to the next session) and the reaction is that session's close-to-close % move for SPY, QQQ, TLT, USO, GLD and IBIT.
| Name | Type | Description |
|---|---|---|
| ids | string[]optional | 1โ60 comma-separated numeric Truth Social post ids (duplicates removed) โ { reactions: { [id]: PostReaction } }. |
| summary | integeroptionaldefault 301โ365 | Look-back window in days โ ImpactSummary. An empty value (?summary=) means 30. |
PostReaction / ImpactSummary// ?ids=114090816417968547
{
"reactions": {
"114090816417968547": {
"session": "2025-02-28", // US session the post maps to; null while pending / no_data
"status": "done", // done | pending | no_data
"moves": { "SPY": -1.59, "QQQ": -2.11, "TLT": 0.42, "USO": -0.8, "GLD": 0.31, "IBIT": -3.2 }
}
}
}
// ?summary=30
{
"days": 30,
"posts": 212, "postsDone": 204, "postsPending": 8,
"postsWithSpyMoveGe1pct": 61,
"avgAbsSpyOnPostingDays": 0.84, // mean |SPY %| over sessions with >= 1 post (null when none)
"avgAbsSpyAllDays": 0.71, // mean |SPY %| over every completed session in the window
"sessions": 21, "postingSessions": 19,
"latestSession": "2026-08-14",
"topPosts": [
{ "id": "...", "created_at": "...", "headline": "...", "headline_en": "...", "url": "...",
"session": "2026-08-14", "spyPct": -2.31, "sessionPosts": 4 }
],
"generatedAt": "2026-08-15T12:00:00.000Z"
}
| Code | Meaning |
|---|---|
| 400 | Neither ids nor summary given; ids not 1โ60 numeric ids; or summary not an integer 1โ365 |
| 500 | Internal error |
pending means the session has not closed or its bars have not arrived yet (files land about 00:10 ET the next day); such rows are re-evaluated after 10 minutes. Unknown ids come back as no_data. The summary is memoised for 10 minutes per days value and lists at most 5 topPosts (one representative post per session).curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/trump-impact?summary=30"
curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/trump-impact?ids=114090816417968547,114090900000000000"
Exactly one of ids or summary is required; ids takes precedence. Posts inside 09:30โ15:45 ET on a session are measured from the last 1-minute bar before the post (mode: rth); anything else is measured from the next session's 09:30 open (mode: session_open).
| Name | Type | Description |
|---|---|---|
| ids | string[]optional | 1โ60 comma-separated numeric post ids (duplicates removed) โ { reactions: { [id]: IntradayReaction } }. |
| summary | stringoptional | Any value (conventionally 1) returns the period summary instead of per-post rows. |
IntradayReaction / IntradaySummaryResponse// ?ids=115123456789012345
{
"reactions": {
"115123456789012345": {
"status": "done", // done | pending | no_data
"mode": "rth", // rth | session_open (null while pending / no_data)
"session": "2026-09-01",
"anchor_ts": "2026-09-01T14:42:00Z", // last 1-minute bar before the post (UTC)
"truncated": false, // session closed before the +60 mark; its last bar was used
"moves": { "SPY": { "m15": 0.21, "m60": -0.05 }, "QQQ": { ... }, "TSLA": { ... } },
"spy15_pct_rank": 62 // |SPY 15m| percentile vs every 15-minute SPY window of the period
}
}
}
// ?summary=1
{
"available": true, // false (other fields null / 0) until the AWS job has delivered a file
"generated_at": "2026-09-02T13:57:00+00:00",
"days": 90,
"window": { "start": "2026-06-04", "end": "2026-09-01" },
"last_session": "2026-09-01",
"baseline": { "symbol": "SPY", "sessions": 62, "n15": 24180, "n60": 22940,
"abs15": { "mean": 0.080, "p50": 0.05, "p75": 0.09, "p90": 0.16, "p95": 0.22, "p99": 0.41 },
"abs60": { ... } },
"summary": {
"posts": 812, "done": 790, "pending": 12, "no_data": 10,
"rth": 310, "session_open": 480, "truncated": 6,
"big_move_pct": 0.5, "spy15_big": 14, "spy15_big_share": 0.018,
"rth_mean_abs_spy15": 0.074, "rth_mean_abs_spy60": 0.15, "session_open_mean_abs_spy15": 0.12,
"baseline_mean_abs15": 0.080, "baseline_mean_abs60": 0.17,
"top": [ { "id": "...", "created_at": "...", "mode": "rth", "session": "...", "anchor_ts": "...",
"spy15": -0.62, "spy60": -0.9, "spy15_pct_rank": 99, "truncated": false, "anchor_posts": 1,
"moves": { ... }, "headline": "...", "headline_en": "...", "url": "..." } ]
}
}
| Code | Meaning |
|---|---|
| 400 | Neither ids nor summary given, or ids not 1โ60 numeric ids |
| 500 | Internal error |
trump_intraday.json, twice daily). Posts outside regular hours are measured from the next session open and flagged session_open. available: false until the job has delivered a file.pending when the post is newer than the snapshot it consumed, no_data otherwise. moves holds SPY, QQQ and up to three of the post's own symbols.curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/trump-intraday?summary=1"
curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/trump-intraday?ids=115123456789012345"
Curated X/Twitter financial posts, per-post analysis and rolling digests.
Newest first. Each post carries _analysis (the cached XAnalysisResult from POST /api/x-analyze or POST /api/x-analyze-batch, or null).
| Name | Type | Description |
|---|---|---|
| page | integeroptionaldefault 1 | Page number (1-based). |
| limit | integeroptionaldefault 50 | Posts per page. |
| before | stringoptional | Cursor: only posts strictly older than this ISO 8601 timestamp (page then counts from there). Invalid โ 400. Added 2026-10-20; the feed pages use it instead of offsets. |
| author | stringoptional | Filter by author handle, exact match (e.g. "WSJ", "zerohedge"). |
XPostPage{
"posts": [
{
"id": "x_2032098083790561289",
"timestamp": "2026-03-17T08:32:00.000Z",
"raw_text": "BREAKING: Fed holds rates steady...",
"author": "Reuters",
"_analysis": { "direction": "neutral", "translation": "...", "one_liner": "...", "one_liner_en": "..." } // or null
}
],
"total": 915,
"page": 1,
"limit": 50,
"hasMore": true
}
curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/x-posts?limit=10"
curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/x-posts?author=Reuters&page=1&limit=20"
Returns the cached result when one exists (with X-AI-Provider: cache); otherwise classifies the headline with the LLM, stores it, and returns it with X-AI-Provider / X-AI-Model headers.
| Name | Type | Description |
|---|---|---|
| message_id | stringrequired | X post ID as returned by /api/x-posts. |
XAnalysisResult{
"direction": "bearish", // bullish|bearish|neutral|uncertain
"translation": "...", // Chinese translation
"one_liner": "...", // Chinese market commentary
"one_liner_en": "..." // English market commentary
}
| Code | Meaning |
|---|---|
| 202 | Analysis already in progress for this post โ retry later |
| 400 | Missing message_id |
| 404 | Message not found |
| 500 | Analysis failed (all LLM providers errored) |
202 if in progress.X-AI-Provider / X-AI-Model headers.curl -H "X-API-Key: $KEY" -X POST https://news.all-vista.org/api/x-analyze -H "Content-Type: application/json" -d '{"message_id": "x_2032098083790561289"}'
Fills the same cache as POST /api/x-analyze for many posts at once. Ids that are already cached or unknown are dropped before the call; only the remaining headlines are sent, in a single prompt. The body reports counts only โ read the results back through /api/x-posts (_analysis).
| Name | Type | Description |
|---|---|---|
| ids | string[]required | 1โ25 X post ids (non-empty strings of at most 64 characters; duplicates removed). |
BatchAnalysisReport{
"requested": 20, // distinct ids in the request
"analyzed": 17, // items the model returned well-formed; written to the cache
"skipped_cached": 2, // ids that already had an analysis (not sent)
"skipped_unknown": 0, // ids not present in the X archive (not sent)
"failed": 1, // sent ids the model skipped or returned malformed
"provider": "anthropic", // null when nothing was sent (no LLM call)
"model": "claude-sonnet-4-6"
}
| Code | Meaning |
|---|---|
| 202 | The same set of uncached ids is already being analysed โ retry later |
| 400 | Body is not JSON, or ids is not an array of 1โ25 non-empty strings (each โค 64 chars) |
| 500 | Batch analysis failed (the LLM call errored; nothing was cached) |
maxDuration is 300 s). Use a client timeout of about 290 s.200 with analyzed: 0 and provider: null without calling the LLM. Otherwise X-AI-Provider / X-AI-Model headers name the provider that ran. Headlines are truncated to 600 characters in the prompt.scripts/analyze_trending.py, which sends the last 24 h of posts for the trending tickers in chunks of 20 (route limit is 25) and counts a 500 as a spent LLM call.X-AI-Provider / X-AI-Model headers.curl -H "X-API-Key: $KEY" -X POST https://news.all-vista.org/api/x-analyze-batch -H "Content-Type: application/json" -d '{"ids": ["x_2032098083790561289", "x_2032098083790561290"]}'
Cached per {window}_{start}: a repeat call with the same window and the identical start string returns the stored digest (with X-AI-Provider: cache). Posts with start <= timestamp < end are summarised.
| Name | Type | Description |
|---|---|---|
| window | stringrequired | Time window label; becomes the prefix of the cache key. 4h12h1d1w |
| start | stringrequired | Window start, ISO 8601 (inclusive). Use the exact form YYYY-MM-DDTHH:MM:SS.000Z so the key matches GET /api/digests. |
| end | stringrequired | Window end, ISO 8601 (exclusive). |
DigestResult{
"sentiment": "bearish", // bullish|bearish|neutral|mixed
"title": "...", // Chinese one-line title
"title_en": "...", // English one-line title
"summary": "...", // Chinese 2-3 paragraph analysis
"summary_en": "...", // English 2-3 paragraph analysis
"key_themes": ["tariffs", "fed policy", "tech earnings"],
"notable_tickers": ["NVDA", "TSLA", "SPY"]
}
| Code | Meaning |
|---|---|
| 202 | Digest for this window/start is already being generated โ retry later |
| 400 | Missing window, start or end; window not one of 4h, 12h, 1d, 1w (window must be one of 4h, 12h, 1d, 1w); or start / end not parseable as ISO-8601 timestamps |
| 404 | No posts in range |
| 500 | Digest failed (all LLM providers errored) |
202 if in progress. Max 300 headlines per digest (the newest 300 in the window).window must be one of the four listed values and start / end must parse as timestamps (Date.parse); all three are checked before the cache lookup. The cache key still uses the raw start string, so send the canonical YYYY-MM-DDTHH:MM:SS.000Z form to hit the same digest as GET /api/digests.X-AI-Provider / X-AI-Model headers.curl -H "X-API-Key: $KEY" -X POST https://news.all-vista.org/api/x-digest -H "Content-Type: application/json" -d '{"window": "1d", "start": "2026-04-01T00:00:00.000Z", "end": "2026-04-02T00:00:00.000Z"}'
BWEnews crypto feed with analysis and digests.
Newest first. source and headline are parsed from raw_text (format **SOURCE: headline**). Each post carries _analysis (the cached BWEAnalysisResult from POST /api/bwe-analyze, or null).
| Name | Type | Description |
|---|---|---|
| page | integeroptionaldefault 1 | Page number (1-based). |
| limit | integeroptionaldefault 50 | Posts per page. |
| before | stringoptional | Cursor: only posts strictly older than this ISO 8601 timestamp (page then counts from there). Invalid โ 400. Added 2026-10-20; the feed pages use it instead of offsets. |
| source | stringoptional | Filter by source, exact match (e.g. "DB", "AggrNews", "Binance EN"). |
BWEPostPage{
"posts": [
{
"id": "bwe_20260401_001",
"timestamp": "2026-04-01T08:00:00.000Z",
"raw_text": "**Binance EN: BTC breaks $90K...**\n...",
"source": "Binance EN",
"headline": "BTC breaks $90K resistance",
"_analysis": {
"direction": "bullish",
"translation": "...",
"one_liner": "...",
"one_liner_en": "..."
}
}
],
"total": 61,
"page": 1,
"limit": 50,
"hasMore": true
}
curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/bwe-posts?limit=10"
curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/bwe-posts?source=Binance%20EN&limit=20"
Returns the cached result when one exists (with X-AI-Provider: cache); otherwise classifies the parsed headline with the LLM, stores it, and returns it with X-AI-Provider / X-AI-Model headers.
| Name | Type | Description |
|---|---|---|
| message_id | stringrequired | BWE post ID as returned by /api/bwe-posts. |
BWEAnalysisResult{
"direction": "bullish", // bullish|bearish|neutral|uncertain
"translation": "...", // Chinese translation
"one_liner": "...", // Chinese market commentary
"one_liner_en": "..." // English market commentary
}
| Code | Meaning |
|---|---|
| 202 | Analysis already in progress for this post โ retry later |
| 400 | Missing message_id |
| 404 | Message not found |
| 500 | Analysis failed (all LLM providers errored) |
202 if in progress.X-AI-Provider / X-AI-Model headers.curl -H "X-API-Key: $KEY" -X POST https://news.all-vista.org/api/bwe-analyze -H "Content-Type: application/json" -d '{"message_id": "bwe_20260312_001"}'
Cached per {window}_{start}: a repeat call with the same window and the identical start string returns the stored digest (with X-AI-Provider: cache). Every post with start <= timestamp < end is sent to the model (no headline cap).
| Name | Type | Description |
|---|---|---|
| window | stringrequired | Time window label; becomes the prefix of the cache key. 4h12h1d1w |
| start | stringrequired | Window start, ISO 8601 (inclusive). Use the exact form YYYY-MM-DDTHH:MM:SS.000Z so the key matches GET /api/digests. |
| end | stringrequired | Window end, ISO 8601 (exclusive). |
DigestResult{
"sentiment": "mixed", // bullish|bearish|neutral|mixed
"title": "...", // Chinese one-line title
"title_en": "...", // English one-line title
"summary": "...", // Chinese 2-3 paragraph analysis
"summary_en": "...", // English 2-3 paragraph analysis
"key_themes": ["BTC ETF", "DeFi regulation"],
"notable_tickers": ["BTC", "ETH", "SOL"]
}
| Code | Meaning |
|---|---|
| 202 | Digest for this window/start is already being generated โ retry later |
| 400 | Missing window, start or end; window not one of 4h, 12h, 1d, 1w (window must be one of 4h, 12h, 1d, 1w); or start / end not parseable as ISO-8601 timestamps |
| 404 | No posts in range |
| 500 | Digest failed (all LLM providers errored) |
202 if in progress.window must be one of the four listed values and start / end must parse as timestamps (Date.parse); all three are checked before the cache lookup. The cache key still uses the raw start string, so send the canonical YYYY-MM-DDTHH:MM:SS.000Z form to hit the same digest as GET /api/digests.X-AI-Provider / X-AI-Model headers.curl -H "X-API-Key: $KEY" -X POST https://news.all-vista.org/api/bwe-digest -H "Content-Type: application/json" -d '{"window": "1d", "start": "2026-04-01T00:00:00.000Z", "end": "2026-04-02T00:00:00.000Z"}'
Read-only access to the hourly X and BWE digests.
Lists every digest stored for a source, optionally narrowed to one window. Entries are sorted by cache key descending, i.e. newest first within each window.
| Name | Type | Description |
|---|---|---|
| source | stringrequired | Which digest store to read. xbwe |
| window | stringoptional | Only digests whose key starts with this window; must be one of the four values when given, omit for all windows (window: "all" in the response).4h12h1d1w |
| from | stringoptional | ISO 8601 lower bound (inclusive) on the digest window start. The feed pages use from/to to fetch digests for older posts as they page in (since 2026-10-20). |
| to | stringoptional | ISO 8601 upper bound (exclusive) on the digest window start. Invalid from/to โ 400. |
DigestList{
"source": "x",
"window": "1d", // "all" when the query had no window
"total": 42,
"digests": [
{
"key": "1d_2026-04-01T00:00:00.000Z", // "{window}_{start}"
"window": "1d",
"start": "2026-04-01T00:00:00.000Z",
"sentiment": "bearish",
"title": "...",
"title_en": "Tariff fears dominate as markets sell off",
"summary": "...",
"summary_en": "...",
"key_themes": ["tariffs", "fed policy"],
"notable_tickers": ["SPY", "QQQ", "NVDA"]
}
]
}
| Code | Meaning |
|---|---|
| 400 | Missing or invalid source (must be x or bwe), or window given but not one of 4h, 12h, 1d, 1w (window must be one of 4h, 12h, 1d, 1w) |
POST /api/x-digest or POST /api/bwe-digest to generate new digests.limit or since parameter: the response is the whole store for the selected window (over a thousand 4h digests, several MB). Always pass window and slice digests[] client-side for the newest N; they are sorted newest first.window, when given, is validated against the same four values as the digest POST routes and then matched as the key prefix {window}_.curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/digests?source=x&window=1d"
curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/digests?source=bwe"
Daily macro brief, live indicators and the economic events calendar.
Formats the latest macro snapshot (live Polygon overlay for equities/ETFs) into a prompt and asks the LLM for a ~350-word institutional-style macro brief. The result is cached in memory per snapshot id and locale, so repeat calls are instant until a new snapshot lands.
| Name | Type | Description |
|---|---|---|
| locale | stringoptionaldefault en | Language of the brief; any value other than zh falls back to en. enzh |
text/plainContent-Type: text/plain; charset=utf-8
X-AI-Provider: anthropic // or "cache" when served from the in-memory cache
X-AI-Model: claude-opus-4-6 // or "cached"
Growth is cooling but not collapsing: payrolls printed +142K against a 4.2% unemployment
rate while real GDP held at 2.1% QoQ ... (~350 words, no title)
| Code | Meaning |
|---|---|
| 404 | No snapshot data available (plain-text body) โ macro.json has no valid snapshot yet |
X-AI-Provider and X-AI-Model indicate which LLM generated the analysis. Cached replays report X-AI-Provider: cache / X-AI-Model: cached.text/plain (~350 words). The prompt includes live S&P 500, Nasdaq, 10Y yield, oil, VIX, BTC, gold, and 20+ macro indicators; indicators without a reading are passed to the model as n/a.ANTHROPIC_MODEL_MACRO, Codex, Qwen). Up to 20 snapshot/locale pairs are kept in the in-memory cache.X-AI-Provider / X-AI-Model headers.curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/macro-analysis?locale=zh"
Returns the latest macro snapshot as JSON. Each indicator is either a price item { close, change_pct } or an economic indicator { value, date }. Categories: market, growth, inflation, risk_appetite, liquidity, fiat_credit, ai_tech, global_markets.
| Name | Type | Description |
|---|---|---|
| category | stringoptional | Restrict to one factor group. marketgrowthinflationrisk_appetiteliquidityfiat_creditai_techglobal_markets |
| keys | string[]optional | Comma-separated indicator keys, e.g. cpi,unemployment_rate,vix; matches are returned grouped by their category (categories with no match are omitted). |
| live | stringoptionaldefault true | Overlay equity/ETF prices with live Polygon.io quotes (indices, crypto and economic indicators stay from the snapshot). Accepts exactly true, false, 1 or 0; any other value is a 400. truefalse10 |
| history | stringoptionaldefault false | Append a history map (~120 daily points each) for indicators without a public ticker: total_pc_ratio, equity_pc_ratio, us_debt_gdp, fiscal_deficit_gdp. Accepts exactly true, false, 1 or 0; any other value is a 400. truefalse10 |
MacroIndicators{
"snapshot_id": "macro_20260511_080005",
"timestamp": "2026-05-11T08:00:05Z",
"live": true,
"indicators": {
"market": {
"sp500": { "close": 7399.2, "change_pct": 0.81 },
"nasdaq": { "close": 26247.1, "change_pct": 1.72 },
"treasury_10y": { "close": 4.36, "change_pct": -0.45 },
"oil": { "close": 99.1, "change_pct": 0.55 }
},
"inflation": {
"cpi": { "value": 3.3, "date": "2026-04-01" },
"core_pce": { "value": 3.2, "date": "2026-03-01" }
}
// ... growth, risk_appetite, liquidity, fiat_credit, ai_tech, global_markets
},
"history": { // only with history=true
"total_pc_ratio": [ { "date": "2026-01-02", "value": 0.91 }, ... ],
"equity_pc_ratio": [ ... ], "us_debt_gdp": [ ... ], "fiscal_deficit_gdp": [ ... ]
}
}
| Code | Meaning |
|---|---|
| 400 | live or history not one of true, false, 1, 0 (live and history accept true|false|1|0); invalid category (body lists valid_categories); or an empty keys parameter |
| 404 | No snapshot data available |
/api/macro-analysis when you want a written brief.live and history are checked before the snapshot is read, so a bad flag value is a 400 even when no snapshot exists; the response echoes the effective live as a JSON boolean.close and value are null when a series has no reading yet (e.g. mag7_avg before the live overlay); render a dash rather than zero.curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/macro-indicators?category=inflation"
curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/macro-indicators?keys=cpi,unemployment_rate,vix,btc"
curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/macro-indicators?live=false&history=true"
Builds a day-bucketed calendar from today (UTC) through today plus days (inclusive). Macro and central-bank releases come from events.json (Unusual Whales for the US, TuShare for CN/HK/GLOBAL), HK results dates from hk_earnings.json, and US earnings from the Finnhub calendar file restricted to revenue estimates of at least $10B. US earnings are tagged with the options-implied move.
| Name | Type | Description |
|---|---|---|
| days | integeroptionaldefault 141โ30 | Number of days ahead to include (window is today through today+days, inclusive); non-numeric values fall back to 14. |
CalendarPayload{
"fetched_at": "2026-09-07T05:05:12+00:00", // events.json fetch time; null when the file is missing
"hk_checked_at": "2026-09-06T02:10:00+00:00", // hk_earnings.json check time; null when missing
"days": [
{
"date": "2026-09-10",
"events": [ // sorted by time_utc, untimed events last
{
"id": "3f9c1a2b7d4e", // sha1(source|date|title)[:12] for macro rows
"date": "2026-09-10",
"time_utc": "12:30", "time_et": "08:30", "time_hkt": "20:30", // null when the release has no time
"region": "US", // US | CN | HK | GLOBAL
"type": "macro", // macro | central_bank | earnings
"importance": "high", // high | normal
"title_zh": "็พๅฝCPIๅๆฏ", "title_en": "CPI YoY",
"prev": "2.9%", "forecast": "3.0%", // as published (strings); null when unknown
"source": "uw", // uw | tushare | hk_list | finnhub
"meta": {}
},
{
"id": "us-BABA-2026-09-10", "date": "2026-09-10",
"time_utc": null, "time_et": null, "time_hkt": null,
"region": "US", "type": "earnings", "importance": "high",
"title_zh": "BABA ่ดขๆฅ", "title_en": "BABA earnings",
"prev": null, "forecast": null, "source": "finnhub",
"meta": { "symbol": "BABA", "hour": "bmo", "hkCode": "09988.HK", "impliedMovePct": 6.8 }
},
{
"id": "hk-00700-2026-09-10", "date": "2026-09-10",
"time_utc": null, "time_et": null, "time_hkt": null,
"region": "HK", "type": "earnings", "importance": "high",
"title_zh": "่
พ่ฎฏๆง่ก ไธ็ปฉ", "title_en": "Tencent results",
"prev": null, "forecast": null, "source": "hk_list",
"meta": { "symbol": "00700", "confirmed": true }
}
]
}
]
}
importance is high for every earnings and central-bank row; macro releases are high only when the title matches a market-moving keyword list (CPI, PPI, PCE, GDP, PMI, ISM, payrolls, FOMC, retail sales, jobless claims, LPR/MLF, ...) and normal otherwise.meta.impliedMovePct (percent, one decimal) is added to at most the first 40 US earnings rows from the Unusual Whales IV term structure (first expiry on/after the report date, cached 12 h); it is absent when no usable term structure exists. meta.hkCode is present only for US tickers that are also listed in Hong Kong.days value. Missing source files are not an error โ the affected rows are simply absent and fetched_at / hk_checked_at are null.curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/events"
curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/events?days=7"
Earnings calendar, realised results and implied-vs-realised moves.
Filters the Finnhub earnings calendar file. Without an explicit date or from the response is forward-looking from today (ET); past results with surprises and price reactions live at /api/earnings/results.
| Name | Type | Description |
|---|---|---|
| tier | stringoptionaldefault all | Revenue-estimate filter: big = at least $100M, mega = at least $10B; case-insensitive, any other value is rejected with 400. allbigmega |
| date | stringoptional | Exact-day filter (YYYY-MM-DD); when set, from no longer defaults to today. |
| from | stringoptionaldefault today (ET) | Inclusive lower bound (YYYY-MM-DD). When neither date nor from is given the response starts at today (ET); pass from explicitly to reach the past week. |
| to | stringoptional | Inclusive upper bound (YYYY-MM-DD). |
| symbol | string[]optional | One or more comma-separated tickers (case-insensitive), e.g. AAPL,MSFT. |
| hour | stringoptional | Reporting time, exact match on the stored value: bmo = before market open, amc = after market close, dmh = during market hours. bmoamcdmh |
| limit | integeroptionaldefault 5000โฆโ10000 | Cap on returned items (total still reports the unfiltered count). |
| group_by | stringoptional | Set to date to receive days[] (each { date, count, entries[] }, ascending by date) instead of a flat items[]. date |
EarningsCalendar{
"source": "finnhub",
"fetched_at": "2026-04-27T05:15:08Z",
"from_date": "2026-04-20", // stored window (file), not the filtered range
"to_date": "2026-05-27",
"total": 7, // matches before limit
"returned": 7,
"filters": { "tier": "mega", "date": null, "from": "2026-04-27", "to": null, "symbol": null, "hour": null },
"items": [
{
"date": "2026-04-29",
"symbol": "AMZN",
"hour": "amc",
"quarter": 1,
"year": 2026,
"epsActual": null,
"epsEstimate": 1.667,
"revenueActual": null,
"revenueEstimate": 180846456490
}
]
// with group_by=date: "days": [ { "date": "2026-04-29", "count": 3, "entries": [ ... ] } ] replaces "items"
}
| Code | Meaning |
|---|---|
| 400 | Unknown tier โ body is { "error": "invalid tier", "valid_tiers": ["all", "big", "mega"] } |
hour values: bmo = before market open, amc = after market close, dmh = during market hours, empty string = unannounced. *Actual fields are null until the company reports.filters.from echoes the effective lower bound, i.e. today (ET) when it was defaulted; filters.tier echoes the lower-cased tier. Items keep the file order (by date); within a day they are not re-sorted.tier is lower-cased before the check, so MEGA works, but anything outside all / big / mega is a 400 (valid_tiers in the body) rather than being treated as all.curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/earnings?symbol=AAPL,MSFT,GOOGL,META,AMZN,NVDA,TSLA&from=2026-04-27&to=2026-05-11"
curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/earnings?tier=mega&group_by=date"
curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/earnings?date=2026-04-29&hour=amc"
Companies with a revenue estimate of at least $1B that reported in the last days ET calendar days (inclusive of today), with surprise percentages, a beat/miss/mixed verdict and the close-to-close move of the session that priced the report.
| Name | Type | Description |
|---|---|---|
| days | integeroptionaldefault 71โ30 | Look-back window in ET calendar days; must be an integer within range (out-of-range or non-integer values are rejected, not clamped). |
ResultsPayload{
"generated_at": "2026-09-02T12:00:03Z",
"from": "2026-08-26", "to": "2026-09-02", "days": 7,
"source_fetched_at": "2026-09-02T05:15:08Z",
"summary": { "reported": 38, "beats": 27, "mixed": 2, "misses": 9, "withReaction": 35, "avgReactionPct": 1.12 },
"items": [
{
"date": "2026-08-27", "symbol": "NVDA", "hour": "amc", "quarter": 2, "year": 2027,
"epsActual": 1.05, "epsEstimate": 1.01, "revenueActual": 46743000000, "revenueEstimate": 46020000000,
"epsSurprisePct": 3.96, "revenueSurprisePct": 1.57,
"verdict": "beat", // beat | miss | mixed | null (no surprise computable)
"beat": true, // compatibility flag: true = beat, false = miss or mixed, null = no verdict
"reactionPct": -0.82, // close-to-close move of the session that priced the report
"reactionBasis": "amc", // amc โ next session (also used for dmh / unknown); bmo โ same session
"reactionSession": "2026-08-28"
}
]
}
| Code | Meaning |
|---|---|
| 400 | days must be an integer between 1 and 30 |
| 500 | failed to build earnings results |
reactionPct is null while the pricing session is still open (sessions count as closed at 16:15 ET) or when a bar is missing.verdict is beat when every available surprise is โฅ 0, miss when every one is < 0, mixed when EPS and revenue disagree in sign. Results are memoised for 5 minutes on the source file's mtime.curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/earnings/results?days=14"
Per-symbol record of how the stock actually moved across each of its recent reports versus what the ATM straddle implied the day before. Either ticker or top=1 is required.
| Name | Type | Description |
|---|---|---|
| ticker | stringoptional | Symbol (case-insensitive, a leading $ is stripped) that must match ^[A-Z][A-Z0-9.-]{0,9}$ after normalisation โ { symbol, generated_at, as_of, record | null }. |
| top | stringoptional | Set to 1 to instead list the symbols with the largest |avg realised โ avg implied| gap (needs at least 4 paired events) โ { generated_at, as_of, coverage, items[] }; takes precedence over ticker. 1 |
| limit | integeroptionaldefault 201โ100 | Row cap for the top=1 board; non-numeric values fall back to the default. |
EarningsVolResponse (ticker=NVDA){
"symbol": "NVDA",
"generated_at": "2026-09-02T18:15:00+00:00",
"as_of": "2026-09-01",
"record": {
"n": 8, "n_implied": 8,
"avg_abs_realised": 6.1, // % close-to-close across the report (BMO: day vs prior; AMC: next vs day)
"avg_implied": 7.4, // % ATM straddle / spot at T-1, nearest expiry after the report
"ratio": 0.82, // realised รท implied
"hit_rate": 0.25, // share of reports where |realised| > implied
"next": { "date": "2026-11-19", "hour": "amc" } | null,
"events": [ { "date": "2026-08-27", "hour": "amc", "period": "Q2 FY27", "session": "2026-08-28", "spot": 181.2, "realised_pct": -3.4, "implied_pct": 6.8, "expiry": "2026-08-29" }, ... ]
} | null
}
// top=1
{
"generated_at": "...", "as_of": "2026-09-01",
"coverage": { "symbols": 1120, "symbols_with_implied": 980, "events": 8400, "events_with_realised": 8100, "events_with_implied": 6900 },
"items": [ { "symbol": "SMCI", "avg_abs_realised": 14.2, "avg_implied": 9.1, "gap": 5.1, "ratio": 1.56, "hit_rate": 0.75, "n_implied": 8, "next": { ... } | null }, ... ] // sorted by |gap| desc
}
| Code | Meaning |
|---|---|
| 400 | ticker missing or not matching ^[A-Z][A-Z0-9.-]{0,9}$ (only when top is not 1) |
| 500 | earnings vol unavailable (unexpected read error) |
| 503 | earnings vol data unavailable โ earnings_vol.json has not been pulled yet |
earnings_vol.json, ~1.1k symbols: market cap โฅ $10B plus anything reporting within ยฑ30 days). 503 while the file is missing; record: null for an uncovered symbol. Powers the card on /stocks and the calendar detail pane.hour can also be dmh (during market hours) or empty; both use the AMC rule for the realised move. events are oldest first, at most 8.curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/earnings-vol?ticker=NVDA"
curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/earnings-vol?top=1&limit=10"
Ticker search, prices, news, fundamentals, factor exposure and options history.
Matches the query against the ticker universe: exact ticker first, then ticker prefixes, then company names containing the query. Within each tier larger market caps come first.
| Name | Type | Description |
|---|---|---|
| q | stringrequired | Search query (min 1 character); case-insensitive. |
| limit | integeroptionaldefault 101โ20 | Max results, clamped to 1โ20; 0 or a non-numeric value falls back to 10. |
SearchResults{
"results": [
{
"ticker": "NVDA",
"name": "NVIDIA Corp",
"market_cap": 2800000000000, // null when unknown
"primary_exchange": "XNAS",
"type": "CS", // CS, ETF, ...
"sic_description": "Semiconductors",
"market_cap_tier": "mega"
}
]
}
q returns 200 with results: [] rather than an error.curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/stock-search?q=nvidia&limit=5"
Reads the local daily aggregates for every weekday in the range (both ends inclusive); weekends and days without a bar are skipped.
| Name | Type | Description |
|---|---|---|
| ticker | stringrequired | Stock/ETF ticker symbol (case-insensitive; echoed back upper-cased). |
| start | stringoptionaldefault 180 days ago | Start date, YYYY-MM-DD (inclusive). |
| end | stringoptionaldefault today (UTC) | End date, YYYY-MM-DD (inclusive). |
OHLCResponse{
"ticker": "NVDA",
"bars": [
{
"date": "2026-03-17",
"open": 142.50,
"high": 145.20,
"low": 141.80,
"close": 144.90,
"volume": 38500000
}
]
}
| Code | Meaning |
|---|---|
| 400 | ticker missing |
200 with an empty bars array (no 404).curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/stock-ohlc?ticker=AAPL&start=2026-01-01"
Looks the ticker up in the server-side news index built from every X post (cashtag, then bare symbol, then company name, with false-positive guards). Posts are newest first with exact-duplicate texts removed.
| Name | Type | Description |
|---|---|---|
| ticker | stringrequired | Stock ticker symbol; dual share classes share one list (GOOGL resolves to GOOG). |
StockNews{
"ticker": "TSLA",
"news": [
{
"id": "x_20320980...",
"timestamp": "2026-03-15T12:00:00.000Z",
"raw_text": "$TSLA deliveries beat expectations...",
"author": "CNBC",
"matchScore": 1.0, // 1.0 = cashtag, 0.9 = bare symbol, 0.8 = company name
"matchReason": "$TSLA",
"matchTier": "cashtag" // "cashtag" | "symbol" | "name"
}
]
}
| Code | Meaning |
|---|---|
| 400 | ticker missing |
200 with an empty news array.curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/stock-news?ticker=TSLA"
Closes on the next 1, 3 and 5 trading days after the event date, expressed as percentage change from the event-day close.
| Name | Type | Description |
|---|---|---|
| ticker | stringrequired | Stock ticker symbol (case-insensitive). |
| date | stringrequired | Event date, YYYY-MM-DD (must be a trading day with a bar for the ticker). |
ForwardReturns{
"eventDate": "2026-03-17",
"eventClose": 144.90,
"t1": { "date": "2026-03-18", "close": 146.20, "returnPct": 0.90 },
"t3": { "date": "2026-03-20", "close": 143.50, "returnPct": -0.97 },
"t5": { "date": "2026-03-24", "close": 148.00, "returnPct": 2.14 } // null until 5 trading days have elapsed
}
| Code | Meaning |
|---|---|
| 400 | ticker or date missing |
date is not a trading day (or the ticker has no bar that day) the route still answers 200 with eventClose: null and t1/t3/t5 all null.returnPct is a percentage (0.90 = +0.90%). A horizon is null while fewer than that many trading days have elapsed since the event.curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/stock-returns?ticker=NVDA&date=2026-03-17"
Builds a prompt from the ticker's OHLC summary, the X posts matched inside the window and (when on file) the SEC fundamentals brief, then returns the model's ~400-word write-up as plain text.
| Name | Type | Description |
|---|---|---|
| ticker | stringrequired | Stock ticker symbol. |
| startDate | stringoptionaldefault 180 days ago | Analysis start date, YYYY-MM-DD. |
| endDate | stringoptionaldefault today (UTC) | Analysis end date, YYYY-MM-DD. |
| locale | stringoptionaldefault en | Output language; any value other than zh falls back to en. enzh |
text/plain// Content-Type: text/plain; charset=utf-8
// X-AI-Provider: <provider> X-AI-Model: <model> ("cache" / "cached" on a memoised hit)
NVDA has spent the last six months in a steady uptrend ...
(~400 words covering technical setup, news impact, 1-2 week outlook and key risk factors)
| Code | Meaning |
|---|---|
| 400 | ticker missing (plain-text body) |
ticker/startDate/endDate/locale (last 50 keys); a hit returns immediately with X-AI-Provider: cache.X-AI-Provider / X-AI-Model headers.curl -H "X-API-Key: $KEY" -X POST https://news.all-vista.org/api/stock-analysis -H "Content-Type: application/json" -d '{"ticker":"NVDA","locale":"zh"}'
Server-side aggregate of everything the site knows about a symbol. Each section is built independently and is null when the module has nothing for the symbol OR its upstream failed; only flow, darkpool and congress carry fetchedAt/stale to tell the two apart. earnings is null whenever the next report is outside the stored earnings window (about 7 days back to 30 days ahead), which is the common case for a name that reported recently.
| Name | Type | Description |
|---|---|---|
| ticker | stringrequired | Symbol matching ^[A-Z][A-Z0-9.-]{0,9}$ (leading $ and lower case are normalised). |
TickerHub{
"symbol": "NVDA",
"generatedAt": "2026-09-02T12:00:03Z",
"todayEt": "2026-09-02",
"info": { "ticker": "NVDA", "name": "NVIDIA Corp", "exchange": "XNAS", "type": "CS", "marketCap": 4.4e12, "marketCapTier": "Mega Cap (>$100B)", "industry": "SEMICONDUCTORS & RELATED DEVICES" } | null, // tier labels are display strings, not enums
"earnings": { "date": "2026-09-24", "hour": "amc", "daysUntil": 15, "quarter": 3, "year": 2026, "epsEstimate": 1.21, "revenueEstimate": 54.1e9, "impliedMovePct": 6.4 } | null, // null unless the next report is within ~30 days
"flow": { "date": "2026-09-02", "count": 42, "highSignalCount": 5, "capped": false, "callPremium": 18400000, "putPremium": 6100000,
"top": [ { "id": "...", "type": "call", "strike": 190, "expiry": "2026-09-19", "premium": 2100000, "isSweep": true, "isFloor": false, "highSignal": true, "createdAt": "..." } ],
"fetchedAt": "...", "stale": false } | null,
"darkpool": { "date": "2026-09-02", "count": 17, "totalPremium": 210000000, "minPremium": 1000000,
"top": [ { "price": 181.2, "size": 172000, "premium": 31200000, "executedAt": "..." } ], "fetchedAt": "...", "stale": false } | null,
"congress": { "count": 4, "latest": [ { "name": "...", "memberType": "house", "txnType": "Purchase", "amounts": "$15Kโ$50K", "transactionDate": "...", "filedAtDate": "..." } ],
"fetchedAt": "...", "stale": false } | null,
"trumpPosts": { "count90d": 2, "latest": [ { "id": "...", "created_at": "...", "headline": "...", "headline_en": "...", "impact_direction": "bullish", "url": "..." } ] } | null,
"mentions": { "daily": [ { "date": "2026-08-20", "count": 12 }, ... ], // 14 ET days, oldest first
"count24h": 9, "count14d": 131,
"latest": [ { "id": "...", "author": "...", "text": "...", "timestamp": "..." } ] } | null,
"optionsHistory": { "ticker": "NVDA", "date": "2026-09-01", "pc_ratio": 0.63, "pct_pc": 41, "total_vol": 2100000, "pct_vol": 55, "median_pc": 0.71 } | null
}
| Code | Meaning |
|---|---|
| 400 | ticker missing or not matching ^[A-Z][A-Z0-9.-]{0,9}$ |
| 500 | ticker hub unavailable |
null when the module has nothing for the symbol or its source failed; mentions has no staleness flag of its own, so check /api/health (x file age) before trusting a low count24h. Powers the strip at the top of /stocks?ticker=.flow, darkpool or congress null) is rebuilt after 20s. Each Unusual Whales call times out after 8s, so a slow upstream nulls its own block instead of failing the request.curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/ticker-hub?ticker=NVDA"
Serves the per-symbol SEC fundamentals JSON written by the AWS job (a plain file read memoised on mtime; nothing queries the market database per request). Money is in whole currency units, ratios are decimal fractions.
| Name | Type | Description |
|---|---|---|
| ticker | stringrequired | Symbol matching ^[A-Z][A-Z0-9.-]{0,9}$ (leading $ and lower case are normalised). |
Fundamentals{
"symbol": "NVDA",
"name": "NVIDIA Corp",
"entity_name": "NVIDIA CORP",
"cik": "0001045810",
"sic": "3674",
"currency": "USD", // statement currency; valuation multiples only when USD
"mixed_currency": false, "has_ifrs": false,
"security_type": "CS", "adr": false, // ADR: market cap + multiples omitted (ADS ratio unknown)
"snapshot_date": "2026-09-01",
"as_of": "2026-09-01",
"latest_filed": "2026-08-27",
"price": { "close": 181.20, "session": "2026-09-01" },
"shares": { "outstanding": 24.3e9, "as_of": "2026-08-22", "source": "dei" }, // source: "dei" | "diluted_wavg" | null
"ttm": { "revenue": 187e9, "gross_margin": 0.73, "operating_margin": 0.61, "net_margin": 0.54, "fcf": 78e9, "quarters": [ ...4 period ends ], ... } | null,
"valuation": { "market_cap": 4.4e12, "pe_ttm": 44.1, "ps_ttm": 23.5, "pb": 41.2, "fcf_yield": 0.018, "eps_ttm": 4.11, "revenue_ttm": 187e9 },
"quarters": [ { "label": "Q2 FY27", "end": "2026-07-26", "fy": 2027, "fq": 2, "filed": "2026-08-27", "derived": false, "revenue": ..., "net_income": ..., "eps_diluted": ..., "revenue_yoy": 0.56, ... } ], // <= 12, oldest first
"annual": [ { "label": "FY26", "fq": null, ... } ], // <= 5, oldest first
"balance": { "end": "2026-07-26", "cash": ..., "debt_total": ..., "net_cash": ..., "total_assets": ..., "total_liabilities": ..., "equity": ... } | null,
"generated_at": "2026-09-02T18:05:58+00:00"
}
| Code | Meaning |
|---|---|
| 400 | ticker missing or not matching ^[A-Z][A-Z0-9.-]{0,9}$ |
| 404 | no company facts for the symbol (ETFs, funds, most foreign filers) |
| 500 | fundamentals unavailable |
fundamentals/<TICKER>.json, ~5,100 symbols). Powers the fundamentals panel on /stocks and the "SEC fundamentals" section of POST /api/stock-analysis.pe_ttm is null when TTM EPS is zero or negative or when statements are not in USD; net_cash = cash + short-term investments - total debt.curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/fundamentals?ticker=NVDA"
Reads factors.json from the AWS job: Ken French daily factors (ff5 + momentum) and a one-year daily OLS of excess total returns for the ~500 largest names plus a few benchmark ETFs. Returns are decimal fractions (0.01 = 1%); sparkline values are cumulative percent. Every window is anchored on latest_factor_date, not today.
| Name | Type | Description |
|---|---|---|
| ticker | stringoptional | Without it: the factor performance table. With it: that symbol's 1-year regression betas (exposure: null outside the ~500 largest names + benchmark ETFs). Leading $ and lower case are normalised; BRK-B is accepted for BRK.B. |
FactorSummary | FactorExposureResponse// GET /api/factors (table)
{
"as_of": "2026-09-02",
"latest_factor_date": "2026-06-30", // Ken French data lags the market by weeks
"factor_lag_days": 64,
"models": { "ff5": [ ... ], ... },
"factor_order": ["MKT_RF", "SMB", "HML", "RMW", "CMA", "MOM", "RF"],
"factors": { "MKT_RF": { "model": "ff5", "last": 0.004, "mtd": 0.012, "qtd": 0.031, "ytd": 0.084, "y1": 0.152, "vol_ann": 0.14,
"spark": [ ...60 ], "spark_start": "2026-04-02", "latest_date": "2026-06-30", "n_1y": 250 }, ... },
"exposure_window": { "start": "2025-06-30", "end": "2026-06-30", "n_dates": 250, "regressors": [ ... ], "min_n": 120 },
"universe": { "count": 512, "benchmarks": ["SPY", "QQQ", ...], "min_market_cap": 2.1e10, "skipped": 3, ... },
"generated_at": "2026-09-02T14:02:00+00:00"
}
// GET /api/factors?ticker=NVDA
{
"ticker": "NVDA",
"exposure": { "beta": { "MKT_RF": 1.47, "SMB": -0.19, "HML": -0.12, "RMW": 0.40, "CMA": -1.45, "MOM": 0.30 },
"alpha_ann": 0.21, "r2": 0.62, "idio_vol_ann": 0.31, "n": 250 } | null,
"latest_factor_date": "2026-06-30",
"exposure_window": { "start": "2025-06-30", "end": "2026-06-30", "n_dates": 250, "regressors": [ ... ], "min_n": 120 },
"generated_at": "2026-09-02T14:02:00+00:00"
}
| Code | Meaning |
|---|---|
| 400 | ticker given but not matching ^[A-Z][A-Z0-9.-]{0,9}$ |
| 500 | factor data unavailable |
| 503 | factors.json has not been produced yet |
503 while factors.json has not been produced. Powers the factor table on /macro and the exposure chip in the ticker hub strip on /stocks.curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/factors"
curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/factors?ticker=NVDA"
Reads options_history.json from the AWS job: for ~36 symbols a 1-year daily option volume series (call/put/P-C/total with percentiles of the latest values) and, for the snapshot window, daily OI totals, a GEX proxy and front-week max pain.
| Name | Type | Description |
|---|---|---|
| ticker | stringoptionaldefault SPY | SPY, QQQ, IWM, DIA, TLT, GLD or one of the ~30 largest stocks; symbols in the response lists the universe. Trimmed, a leading $ stripped and upper-cased like the other ticker routes, then must match ^[A-Z][A-Z0-9.-]{0,9}$. |
OptionsHistoryResponse{
"generated_at": "2026-09-02T18:16:00+00:00",
"as_of": "2026-09-01",
"window": { "start": "2025-09-02", "end": "2026-09-01" },
"snapshot_start": "2026-08-11", // first day with greeks / OI snapshots
"max_pain_horizon_days": 7,
"symbols": ["SPY", "QQQ", ..., "AAPL", ...], // ETFs first, then stocks
"universe": { "etfs": [ ... ], "stocks": [ ... ] },
"ticker": "SPY",
"data": {
"kind": "etf",
"dates": [ ...250 ], "call_vol": [ ... ], "put_vol": [ ... ], "pc_ratio": [ ... ], "total_vol": [ ... ], // oldest first, aligned by index
"oi": { "dates": [ ... ], "call_oi": [ ... ], "put_oi": [ ... ], "pc_oi": [ ... ], "gex": [ ... ], "max_pain": [ ... ], "mp_exp": [ ... ], "spot": [ ... ] },
"pct": { "pc_ratio": 62, "total_vol": 48 }, // percentile of the latest value within the year
"median": { "pc_ratio": 0.91, "total_vol": 2950000 },
"latest": { "date": "2026-09-01", "call_vol": 1640000, "put_vol": 1360000, "total_vol": 3000000, "pc_ratio": 0.83 }
} | null
}
| Code | Meaning |
|---|---|
| 400 | ticker not matching ^[A-Z][A-Z0-9.-]{0,9}$ (1-10 characters) |
| 500 | options history unavailable |
| 503 | options_history.json missing |
options_history.json). GEX is a proxy (ฮฃ gamma ร OI ร 100 ร spotยฒ ร 0.01, calls โ puts); OI comes from Polygon snapshots (a few % under OCC). data: null outside the universe, 503 while the file is missing. Powers the History tab on /flow and the P/C context line in the ticker hub strip.curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/options-history?ticker=QQQ"
Market tide, gamma exposure, dark pool prints, congressional trades, mood and the daily flow recap.
Unusual Whales market tide (/api/market/market-tide), one point per minute-ish bucket for the current session, mapped to short keys. Served from the in-process UW cache: 2 min TTL while the market is open, 30 min otherwise; the last good payload is returned with degraded: true if UW fails, and the route answers 503 when UW fails with nothing cached.
None.
TideResponse{
"items": [
{
"t": "2026-09-04T09:30:00-04:00", // ET-offset ISO timestamp of the bucket
"call": 12345678.9, // net call premium, USD (cumulative for the session)
"put": -4567890.1, // net put premium, USD
"vol": 154321 // net option volume, contracts
},
...
],
"fetched_at": "2026-09-04T14:31:02.117Z", // when the UW payload was fetched (null in the 503 body)
"market_open": true, // MonโFri 09:30โ16:00 ET
"degraded": false, // true = stale-on-error payload (200) or the empty 503 body
"freshness": { "kind": "intraday", "state": "live", "asOf": "2026-09-04T14:31:02.117Z", "ageMinutes": 0.4 } // live | delayed | stale | offline (session-aware)
}
// 503 โ Unusual Whales failed and nothing was cached yet
{ "items": [], "fetched_at": null, "market_open": true, "degraded": true, "error": "Unusual Whales unavailable" }
| Code | Meaning |
|---|---|
| 503 | Unusual Whales unavailable and nothing cached โ same body shape with items: [], fetched_at: null, degraded: true and error |
degraded: true is a stale cache hit served because the live UW call failed. A 503 (error: "Unusual Whales unavailable", empty items, fetched_at: null) means UW was unreachable and nothing was cached yet.freshness (every flow route since 2026-10-20): state is live (fetched โค 5 min ago in session, or since the latest session open when the market is closed), delayed (โค 60 min in session, or the previous session), stale (older) or offline (nothing cached โ the 503 bodies). asOf is the fetch time, ageMinutes its age. The cache is persisted to disk, so a restart keeps the last good payloads.curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/flow/tide"
Unusual Whales spot exposures per strike (/api/stock/{ticker}/spot-exposures/strike, full chain of up to 500 strikes). The route keeps strikes within ยฑ12% of spot, picks the 34 closest to spot and orders them top-down; callWall is the strike with the largest call gamma and putWall the strike with the most negative put gamma inside that window. Same UW cache as the other flow routes (2 min open / 30 min closed): stale-on-error with degraded: true, 503 when UW fails with nothing cached.
| Name | Type | Description |
|---|---|---|
| ticker | stringoptionaldefault SPY | Underlying symbol (case-insensitive); only the ten listed tickers are accepted. SPYQQQIWMNVDAAAPLTSLAMSFTMETAAMZNGOOGL |
GexResponse{
"ticker": "SPY",
"spot": 648.12, // underlying price reported by UW (0 when no data)
"strikes": [ // โค 34 strikes within ยฑ12% of spot, highest strike first
{
"strike": 660,
"callG": 812345678.5, // dealer call gamma exposure (open-interest based), USD per 1% move
"putG": -234567890.2, // dealer put gamma exposure, always โค 0 (sign normalised)
"net": 577777788.3 // callG + putG
},
...
],
"callWall": 650, // strike with the largest callG in the window
"putWall": 640, // strike with the most negative putG in the window
"fetched_at": "2026-09-04T14:31:02.117Z",
"market_open": true,
"degraded": false,
"freshness": { "kind": "intraday", "state": "live", "asOf": "2026-09-04T14:31:02.117Z", "ageMinutes": 0.4 } // live | delayed | stale | offline (session-aware)
}
| Code | Meaning |
|---|---|
| 400 | Unsupported ticker โ ticker is not one of the ten allowed symbols |
| 503 | Unusual Whales unavailable and nothing cached โ same body shape with spot: 0, empty strikes, both walls 0, fetched_at: null, degraded: true and error |
degraded: true (200). With nothing cached the route answers 503 with spot: 0, empty strikes, both walls 0, fetched_at: null and error: "Unusual Whales unavailable".curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/flow/gex?ticker=SPY"
curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/flow/gex?ticker=nvda"
Unusual Whales recent dark-pool prints (/api/darkpool/recent, UW caps the page at 200) sorted by premium and cut to the top 10. Served from the in-process UW cache (2 min while the market is open, 30 min otherwise) with stale-on-error fallback; 503 when UW fails with nothing cached.
None.
DarkpoolResponse{
"items": [ // top 10 by premium, largest first
{
"ticker": "NVDA",
"price": 176.42, // execution price
"size": 1250000, // shares
"premium": 220525000, // notional, USD (price ร size)
"executedAt": "2026-09-04T14:05:11.000Z" // ISO UTC
},
...
],
"fetched_at": "2026-09-04T14:31:02.117Z",
"market_open": true,
"degraded": false,
"freshness": { "kind": "intraday", "state": "live", "asOf": "2026-09-04T14:31:02.117Z", "ageMinutes": 0.4 } // live | delayed | stale | offline (session-aware)
}
| Code | Meaning |
|---|---|
| 503 | Unusual Whales unavailable and nothing cached โ same body shape with items: [], fetched_at: null, degraded: true and error |
degraded: true is a stale cache hit; a 503 carries error: "Unusual Whales unavailable" and empty items.curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/flow/darkpool"
Unusual Whales recent congress trades (/api/congress/recent-trades, latest 100 filings) filtered to disclosures whose filedAtDate falls within the last 14 calendar days. Served from the in-process UW cache (2 min while the market is open, 30 min otherwise) with stale-on-error fallback; 503 when UW fails with nothing cached.
None.
CongressResponse{
"items": [
{
"name": "Nancy Pelosi", // reporter name (falls back to the filer name)
"memberType": "house", // house | senate
"ticker": "NVDA",
"txnType": "Buy", // Buy | Sell | ... as reported by UW
"amounts": "$1,000,001 - $5,000,000", // disclosure bracket, not an exact figure
"transactionDate": "2026-08-21", // YYYY-MM-DD
"filedAtDate": "2026-09-02" // YYYY-MM-DD; only filings โค 14 days old are kept
},
...
],
"fetched_at": "2026-09-04T14:31:02.117Z",
"market_open": true,
"degraded": false,
"freshness": { "kind": "intraday", "state": "live", "asOf": "2026-09-04T14:31:02.117Z", "ageMinutes": 0.4 } // live | delayed | stale | offline (session-aware)
}
| Code | Meaning |
|---|---|
| 503 | Unusual Whales unavailable and nothing cached โ same body shape with items: [], fetched_at: null, degraded: true and error |
transactionDate can be well outside the 14-day window that applies to filedAtDate.degraded: true is a stale cache hit; a 503 carries error: "Unusual Whales unavailable" and empty items.curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/flow/congress"
Aggregates three Unusual Whales feeds in parallel: daily in/outflow for SPY, QQQ, IWM and DIA (/api/etfs/{T}/in-outflow, latest 10 days), market-wide insider purchases vs sales per filing day (/api/market/insider-buy-sells, 14 days) and the sector ETF table (/api/market/sector-etfs). Each feed uses the shared UW cache (2 min open / 30 min closed); a failed feed comes back empty and flips degraded while the rest is still returned. When every feed fails with nothing cached the route answers 503.
None.
MoodResponse{
"etf": {
"SPY": [ // newest first, โค 10 days
{ "date": "2026-09-03", "prem": -812345678, "close": 646.9 }, // prem = net fund flow, USD
...
],
"QQQ": [ ... ], "IWM": [ ... ], "DIA": [ ... ] // an empty array means that feed failed
},
"insider": [ // per filing day, โค 14 rows
{
"date": "2026-09-03",
"buys": 118, // number of purchase filings
"buyN": 45120000, // purchase notional, USD (absolute)
"sells": 402,
"sellN": 1210500000
},
...
],
"sectors": [
{
"ticker": "XLK",
"name": "Technology Select Sector SPDR Fund",
"last": 245.31,
"changePct": 0.84, // (last โ open) / open ร 100, 0 when open is missing
"callPrem": 91234567, // today's call premium, USD
"putPrem": 45678901, // today's put premium, USD
"flow": -12345678 // latest daily in/out flow, USD
},
...
],
"fetched_at": "2026-09-04T14:29:40.002Z", // OLDEST UW cache timestamp among the feeds that answered (null in the 503 body)
"market_open": true,
"degraded": false, // true if any of the three feeds was stale or failed
"freshness": { "kind": "intraday", "state": "live", "asOf": "2026-09-04T14:31:02.117Z", "ageMinutes": 0.4 } // live | delayed | stale | offline (session-aware)
}
| Code | Meaning |
|---|---|
| 503 | Unusual Whales unavailable โ every feed failed with nothing cached; same body shape with empty etf arrays, insider: [], sectors: [], fetched_at: null, degraded: true and error |
fetched_at is the oldest cache timestamp among the six UW requests that answered (four ETF flows, insiders, sectors), so every section is at least that fresh; individual sections may be newer. It is null only in the 503 body.degraded is true. Only when all feeds fail is the status 503 with error: "Unusual Whales unavailable".curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/flow/mood"
Unusual Whales flow alerts (/api/option-trades/flow-alerts, 200 most recent with min_premium=250000) normalised to numbers and filtered to premium โฅ $250K and 1โ60 days to expiry, newest first, at most 120 rows. highSignal marks the strict subset used by the daily recap: premium โฅ $500K, 7โ42 DTE, sweep or floor print, and ask-side premium above bid-side. Served from the shared UW cache (2 min open / 30 min closed) with stale-on-error fallback; 503 when UW fails with nothing cached.
None.
FlowAlertsResponse{
"items": [ // newest first, โค 120
{
"id": "1a2b3c4d-...", // UW alert id
"ticker": "NVDA",
"type": "call", // call | put
"strike": 180,
"expiry": "2026-09-19", // YYYY-MM-DD
"premium": 1250000, // total premium, USD
"askSidePremium": 1100000,
"bidSidePremium": 150000,
"isSweep": true,
"isFloor": false,
"rule": "RepeatedHits", // UW alert rule name
"createdAt": "2026-09-04T14:02:31.000Z", // ISO
"underlyingPrice": 176.4,
"volume": 8420,
"openInterest": 15310,
"highSignal": true // โฅ $500K, 7โ42 DTE, sweep/floor, ask > bid
},
...
],
"fetched_at": "2026-09-04T14:31:02.117Z",
"market_open": true,
"degraded": false,
"freshness": { "kind": "intraday", "state": "live", "asOf": "2026-09-04T14:31:02.117Z", "ageMinutes": 0.4 } // live | delayed | stale | offline (session-aware)
}
| Code | Meaning |
|---|---|
| 503 | Unusual Whales unavailable and nothing cached โ same body shape with items: [], fetched_at: null, degraded: true and error |
degraded: true is a stale cache hit; a 503 carries error: "Unusual Whales unavailable" and empty items.curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/flow/alerts"
Returns the recap file written by POST /api/flow/recap (stored at /root/data/flow/recap.json, overridable via FLOW_RECAP_PATH). It is regenerated once per US trading day after the close, so date is the ET trading date the recap covers; the previous recap is kept if a generation fails. A store file that is not valid JSON yields 503 until the next successful POST replaces it.
None.
FlowRecapFile{
"date": "2026-09-04", // ET trading date the recap covers
"generated_at": "2026-09-04T21:16:40.512Z", // ISO UTC
"provider": "remote_claude", // LLM provider that produced it
"model": "claude-sonnet-4-6",
"data": {
"sentiment": "mixed", // bullish | bearish | neutral | mixed
"title": "ๅๅฏผไฝ็ๆถจๅคงๅไธปๅฏผ๏ผๆๆฐๅฏนๅฒไปๅจ",
"title_en": "Semis lead call buying while index hedges persist",
"summary": "2โ3 ๆฎตไธญๆๅค็ โฆ",
"summary_en": "2โ3 paragraph English recap ...",
"key_tickers": ["NVDA", "SPY", "AMD"] // uppercase, โค 8
}
}
| Code | Meaning |
|---|---|
| 404 | No recap yet โ the file has never been generated |
| 503 | Recap store file is corrupt (regenerate with POST) โ body is { error, hint } |
curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/flow/recap"
Idempotent per ET trading day. On a weekend or NYSE holiday nothing is generated (200, skipped: true). When the store already holds a recap whose date is today and force is not true, that recap is returned with cached: true and X-AI-Provider: cache โ no LLM or Unusual Whales call. Otherwise the route pulls four Unusual Whales feeds (flow alerts โฅ $250K, market tide, dark-pool prints, latest 50 congress trades), keeps only high-signal alerts (โฅ $500K, 7โ42 DTE, sweep/block, ask-side), aggregates the top 8 tickers by premium, top 5 dark-pool prints and 8 congress trades, then asks the LLM for a strict-JSON bilingual recap. The result is written to the recap store and returned; the cron calls this on weekdays after the US close.
| Name | Type | Description |
|---|---|---|
| force | booleanoptionaldefault false | Regenerate even if today's recap already exists; must be the JSON boolean true (any other value, or no body, means false). |
FlowRecapFile// Fresh generation โ same shape as GET /api/flow/recap, plus X-AI-Provider / X-AI-Model response headers
{
"date": "2026-09-04",
"generated_at": "2026-09-04T21:16:40.512Z",
"provider": "remote_claude",
"model": "claude-sonnet-4-6",
"data": {
"sentiment": "mixed", // bullish | bearish | neutral | mixed
"title": "...", "title_en": "...",
"summary": "...", "summary_en": "...",
"key_tickers": ["NVDA", "SPY"]
}
}
// Same day, recap already stored and force is not true โ X-AI-Provider: cache, X-AI-Model: cached
{ "date": "2026-09-04", "generated_at": "...", "provider": "...", "model": "...", "data": { ... }, "cached": true }
// NYSE closed (America/New_York date) โ nothing is generated, nothing is stored
{ "skipped": true, "reason": "weekend", "date": "2026-09-06" }
{ "skipped": true, "reason": "holiday", "holiday": "Labor Day", "date": "2026-09-07" }
{ "skipped": true, "reason": "stale_upstream", "as_of": "2026-10-17T01:15:02.000Z", "date": "2026-10-20" }
// 202 โ another generation is already running in this process
{ "status": "in_progress", "date": "2026-09-04" }
| Code | Meaning |
|---|---|
| 202 | Another generation is already running โ body { status: "in_progress", date }; retry in a minute (the finished recap is then served as cached: true) |
| 500 | Recap generation failed โ both LLM attempts failed (or the store refused the write); the previous recap file is left untouched |
| 502 | Upstream data unavailable โ one of the four Unusual Whales requests failed with nothing cached |
maxTokens 4096, route maxDuration 300 s) and four Unusual Whales requests, and is counted against the stricter LLM rate limit (60 per IP / 600 global per 5 min) for the public key. Same-day repeats without force: true are free: they return the stored recap with cached: true and X-AI-Provider: cache / X-AI-Model: cached.{ "force": true }, so an earlier same-day call (for example a pre-market regeneration) never blocks the end-of-day recap. The JSON body is optional and only force is read; a missing or non-JSON body counts as force: false. Provider chain and models come from ANTHROPIC_MODEL_FLOW_RECAP, CODEX_MODEL_FLOW_RECAP and QWEN_MODEL_FLOW_RECAP (falling back to the site-wide defaults); the picked provider/model are echoed in X-AI-Provider / X-AI-Model.reason (weekend, holiday or, since 2026-10-20, stale_upstream when Unusual Whales has not refreshed since the latest session open โ as_of is the newest fetch), the holiday name in holiday, and the ET date; force does not override it.GET /api/flow/recap answers 503.X-AI-Provider / X-AI-Model headers.curl -H "X-API-Key: $KEY" -X POST "https://news.all-vista.org/api/flow/recap"
curl -H "X-API-Key: $KEY" -X POST "https://news.all-vista.org/api/flow/recap" -H "Content-Type: application/json" -d '{"force": true}'
A-share market overview, A/H premium and Stock Connect flows.
Both payloads are pre-computed files (china_market.json from the AWS job, hsgt.json from the Finland TuShare fetch); nothing is queried per request. No query parameters.
None.
ChinaMarketBundle{
"market": {
"session_date": "2026-09-01",
"indices": [ { "code": "000001.SH", "name_en": "SSE Composite", "close": 3851.2, "pct": 0.42, "amount_bn": 944.1, "spark": [ ... 60 ] } ],
"industries": [ { "industry": "ๅๅฏผไฝ", "name_en": "Semiconductors", "count": 162, "med_pct": 1.8, "adv": 120, "dec": 40, "amount_bn": 210.3, "top": { ... } } ],
"breadth": { "total": 5312, "advancers": 3105, "decliners": 1980, "limit_up": 61, "limit_down": 7, "st_count": 168, "turnover_bn": 2054.0, "buckets": [ ... ], "by_board": [ ... ] } | null,
"movers": { "by_amount": [ ... ], "gainers": [ ... ], "losers": [ ... ] },
"generated_at": "2026-09-02T13:49:00+00:00"
} | null,
"hsgt": {
"session_date": "2026-09-01",
"flows": [ { "date": "2026-09-01", "north": 1350.2, "hgt": 640.1, "sgt": 710.1, "south": 480.3 } ], // CNY 100m, 60 sessions
"top10": { "sh": [ { "symbol": "600519.SH", "name": "่ดตๅท่
ๅฐ", "close": 1480.0, "pct": 0.9, "amount_m": 2130.5 } ], "sz": [ ... ] },
"generated_at": "..."
} | null,
"ages": { "market_hours": 4.5, "hsgt_hours": 4.6 } // hours since each file's generated_at; null when that file is missing
}
| Code | Meaning |
|---|---|
| 500 | Failed to read China market data |
| 503 | China market data not available yet โ neither china_market.json nor hsgt.json exists (body also carries the empty bundle) |
503 only while neither file exists yet; when just one is missing its block is null and the response is still 200.curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/china/market"
Joins the two AWS job files (A + H closes, ADR closes + FRED DEXCHUS) into one snapshot with an equal-weight premium index, sector medians and per-pair rows. Memoised until one of the files changes on disk. No query parameters.
None.
AhSnapshot{
"available": true, // false (with "reason") until both job files and an FX rate exist
"generated_at": "2026-09-02T13:57:00+00:00",
"stale": false, // true when either source file is older than 72 h
"as_of": "2026-09-01",
"fx": { "cny_per_usd": 7.12, "cny_per_hkd": 0.913, "hkd_per_usd": 7.80, "date": "2026-08-29" },
"index": { "latest": 41.9, "date": "2026-09-01", "chg1d": -0.3, "chg20d": 1.8, "min": 35.1, "max": 47.8, "median": 40.2, "pairs_used": 38,
"series": [ { "d": "2026-03-10", "v": 38.2 }, ... 120 ] }, // equal-weight A/H premium, %
"sectors": [ { "sector": "Banks", "count": 9, "median": 27.4 } ],
"pairs": [ { "a": "601398.SH", "h": "01398.HK", "name_en": "ICBC", "sector": "Banks", "date": "2026-09-01", "a_cny": 7.21, "h_hkd": 5.90, "a_hkd": 7.89, "premium": 33.8, "chg1d": ..., "chg20d": ..., "spark": [ ... ] } ],
"adr": [ { "adr": "BABA", "h": "09988.HK", "ratio": 8, "adr_usd": 132.1, "h_hkd": 128.9, "adr_hkd": 128.8, "premium": -0.34, ... } ],
"adr_skipped": [ { "adr": "...", "h": "...", "reason": "ratio_unverified" } ], // ratio_unverified | no_adr_bars | no_h_bars | no_overlap
"dropped": []
}
| Code | Meaning |
|---|---|
| 500 | A/H premium unavailable (unexpected read error) |
ah_pairs_cnhk.json, ah_pairs_us.json); available: false with a reason (no_cnhk, no_us, no_fx, no_sessions) until both exist.available and stale instead. fx and index are null in the unavailable case; sectors, pairs and adr are empty arrays.curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/china/ah"
Serves cn_pro.json produced by the AWS CN/HK job. Both sections are returned by default; section restricts the payload to one of them.
| Name | Type | Description |
|---|---|---|
| section | stringoptional | Return one section only; an empty value is treated as no filter. fundscbs |
CnProResponse{
"generated_at": "2026-09-02T14:07:00+00:00",
"age_hours": 4.2,
"dates": { "trade_date": "2026-09-01", "fund_period": "2026-06-30", "fund_prev_period": "2026-03-31" },
"funds": { // omitted when section=cbs
"period": "2026-06-30", "prev_period": "2026-03-31",
"universes": { "all": { "top": [ { "code": "600519.SH", "name": "่ดตๅท่
ๅฐ", "industry": "็ฝ้
", "funds": 1412, "mkv": 1580.2, "d_funds": -38, "d_mkv": -92.1 } ], "increases": [ ... ], "decreases": [ ... ], "n_funds": 8123, "total_mkv": 27110.5 }, "active": { ... } },
"top_funds": [ { "code": "005827.OF", "name": "...", "top10_mkv": 210.4, "ret_1m": 3.1, "ret_3m": 9.8 } ]
},
"cbs": { // omitted when section=funds
"session_date": "2026-09-01",
"rows": [ { "code": "113050.SH", "name": "ๅ้ถ่ฝฌๅบ", "stk_code": "601009.SH", "close": 121.3, "pct_chg": 0.4, "conv_price": 8.02, "stk_close": 9.10, "premium": 6.9, "ytm": -1.2, "call": { "type": "ๅ
ฌๅๆ็คบๅผบ่ต", "call_date": "2026-09-20" } | null, ... } ],
...
}
}
| Code | Meaning |
|---|---|
| 400 | section must be 'funds' or 'cbs' |
| 500 | cn_pro unavailable (unexpected read error) |
| 503 | cn_pro data not available yet โ the AWS job has not produced cn_pro.json |
503 while cn_pro.json has not been produced; 400 for an unknown section.curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/china/pro"
curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/china/pro?section=cbs"
The cross-source morning brief.
Read-only aggregation of caches the site already maintains (macro snapshot, today's calendar, latest X and BWE digests, flow recap, Trump impact). No query parameters; the brief is memoised server-side for 60 s and shared across concurrent callers.
None.
Brief{
"generated_at": "2026-09-02T11:30:00.000Z",
"date_et": "2026-09-02",
"glance": { "zh": "...", "en": "..." } | null, // one-line header
"markets": { "source_updated_at": "...", "headline": [ { "key": "sp500", "label": "S&P 500", "close": 6512.3, "change_pct": -0.42 } ], "movers": [ ... ] } | null,
"calendar": { "date": "2026-09-02", "items": [ ... ] } | null, // high-importance events + mega-cap earnings today
"x_digest": { "window": "1d", "sentiment": "bearish", "title_en": "...", "summary_en": "...", "key_themes": [...], "notable_tickers": [...] } | null,
"bwe_digest": { ... } | null,
"flow_recap": { "date": "2026-09-01", "title_en": "...", "summary_en": "...", "key_tickers": ["NVDA", "TSLA"] } | null,
"trump": { "since": "2026-09-01T11:30:00.000Z", "total_posts": 14, "analyzed_posts": 11, "items": [ { "id": "...", "headline_en": "...", "impact_direction": "bearish", "impact_magnitude": 2, "suggested_symbols": ["SPY"] } ] }
}
| Code | Meaning |
|---|---|
| 500 | Brief unavailable |
null when its source is unavailable, so consumers should treat every block as optional (trump is always present, possibly with empty items). scripts/push_brief.py posts this payload to a webhook at 07:30 ET.curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/brief"
Site-wide search and the hourly trending board.
Case-insensitive AND-substring search: every whitespace-separated token (max 8, a leading $ is stripped) must appear in the item. Corpora, in result order: a synthetic ticker hit when the query is $SYM or a lone UPPERCASE token that resolves in the ticker table; Trump Truth Social posts (text plus cached AI headline and card title); X headlines (text + author); BWE wire posts (headline, text, source); and X/BWE AI digests (titles, key themes, notable tickers). Reads the on-disk data files directly with memoised indexes, so results reflect the latest fetched data.
| Name | Type | Description |
|---|---|---|
| q | stringrequired | Search text; trimmed, must be 2โ100 characters. |
| limit | integeroptionaldefault 301โ60 | Total results to return; each content type contributes at most 10, and trimming to the limit keeps every matching type represented. |
| lang | stringoptionaldefault en | Which language of AI headlines/digest titles to prefer in title; any other value falls back to en.enzh |
SearchResponse{
"q": "$NVDA export",
"lang": "en",
"took_ms": 12.4,
"counts": { // total matches per type BEFORE the per-type cap of 10
"ticker": 1, "trump": 3, "x": 87, "bwe": 5, "digest": 2
},
"results": [ // grouped: ticker โ trump โ x โ bwe โ digest, newest first within a group
{
"type": "ticker", // ticker | trump | x | bwe | digest
"id": "NVDA",
"title": "NVDA ยท NVIDIA Corp",
"snippet": "XNAS ยท CS ยท mega", // exchange ยท type ยท market-cap tier
"timestamp": "", // "" for the ticker hit, ISO otherwise
"href": "/stocks?ticker=NVDA", // locale-less internal link
"meta": "SEMICONDUCTORS & RELATED DEVICES"
},
{
"type": "trump",
"id": "114090816417968547",
"title": "Trump threatens new chip export curbs", // AI headline (lang-aware) or truncated text
"snippet": "โฆa ~150-char window around the first token hitโฆ",
"timestamp": "2026-09-03T18:22:10.000Z",
"href": "/trump?post=114090816417968547",
"externalUrl": "https://truthsocial.com/@realDonaldTrump/114090816417968547",
"meta": "@realDonaldTrump"
},
{ "type": "x", "id": "1963...", "title": "NVIDIA says export ...", "snippet": "", "timestamp": "...", "href": "/x", "meta": "DeItaone" },
{ "type": "bwe", "id": "...", "title": "...", "snippet": "ไธญๆ่ฏๆโฆ", "timestamp": "...", "href": "/bwe", "meta": "Reuters" },
{ "type": "digest", "id": "x:24h_2026-09-03T00:00:00.000Z", "title": "...", "snippet": "theme ยท theme", "timestamp": "2026-09-03T00:00:00.000Z", "href": "/x", "meta": "X ยท 24h" }
]
}
| Code | Meaning |
|---|---|
| 400 | q shorter than 2 or longer than 100 characters, or limit not a number in 1โ60 |
| 500 | search failed โ a data file could not be read |
$oil-style cashtags or uppercase to force the ticker hit.curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/search?q=tariff%20china&limit=20"
curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/search?q=%24NVDA&lang=zh"
Walks the per-ticker X headline index (cashtag, bare symbol and company-name matching from the /stocks matcher) and ranks common stocks and ADRs with โฅ 3 mentions in the last 24 h by 24 h count, then by the ratio to their 7-day daily average. The ranking is recomputed in-process at most every 5 minutes; the sentiment column comes from the per-post AI analysis cache, which scripts/analyze_trending.py refreshes hourly for the current trending tickers.
| Name | Type | Description |
|---|---|---|
| limit | integeroptionaldefault 151โ50 | Number of tickers to return; must be an integer in 1โ50 (an empty value or anything that is not an integer is rejected with 400). |
TrendingSnapshot{
"generated_at": "2026-09-04T14:30:00.000Z", // when the ranking was last computed (โค 5 min old)
"items": [ // sorted by count24h desc, then ratio desc, then ticker
{
"ticker": "NVDA",
"name": "Nvidia", // short display name (corporate suffixes stripped)
"count24h": 42, // headlines mentioning it in the last 24 h (โฅ 3 to appear)
"avgDaily7d": 11.57, // headlines per day over the previous 7 full days
"ratio": 3.63, // count24h / max(avgDaily7d, 0.5)
"sentiment": { // AI direction mix of the analysed 24 h posts, or null if none analysed
"bullish": 12, "bearish": 5, "neutral": 9, "uncertain": 2,
"total": 28 // posts with an analysis; shares are x / total
},
"latest": { // newest headline mentioning the ticker, or null
"id": "1963512345678901234",
"author": "DeItaone",
"raw_text": "NVIDIA SAYS ...",
"timestamp": "2026-09-04T14:12:05.000Z"
}
},
...
]
}
| Code | Meaning |
|---|---|
| 400 | limit is empty, not an integer, or outside 1โ50 (limit must be an integer between 1 and 50) |
| 500 | trending unavailable โ the X posts, ticker table or analysis cache could not be read |
limit is validated like /api/search (parsed as a number, then range-checked) but must additionally be a whole number: fractional values such as 7.5 are rejected rather than floored.curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/trending?limit=10"
Health and freshness of every data file behind the site.
Reports the age of each data file the site reads and whether it is older than that file's threshold. Pushed feeds (x, macro, bwe, events, earnings under /root/data/*) are judged by file mtime against 48 h. AWS market-database files under aws_data_dir are judged by their payload generated_at (mtime as fallback): china_market and hsgt 80 h (A-share files only move on CN trading days), ah_pairs_cnhk and ah_pairs_us 48 h, trump_intraday, factors, cn_pro, earnings_vol and options_history 36 h. fundamentals is judged by fundamentals_index.json: index โค 36 h old, count โฅ 4000 symbols and zero failed_batches. A missing file reports ageHours: null and stale: true; anyStale is the overall status and also drives the HTTP status: 200 when every file is fresh, 503 when any file is stale (same JSON body either way).
None.
HealthResponse// This example is served with HTTP 503 because anyStale is true; the body is identical on a 200
{
"checked_at": "2026-09-04T14:31:02.117Z",
"stale_threshold_hours": 48, // default threshold for the pushed feeds
"aws_data_dir": "/root/data/aws",
"files": [ // 15 entries: 5 pushed, 9 AWS, fundamentals
{ "key": "x", "ageHours": 0.4, "stale": false, "thresholdHours": 48 },
{ "key": "macro", "ageHours": 6.1, "stale": false, "thresholdHours": 48 },
{ "key": "bwe", "ageHours": 1.2, "stale": false, "thresholdHours": 48 },
{ "key": "events", "ageHours": 9.5, "stale": false, "thresholdHours": 48 },
{ "key": "earnings", "ageHours": 52.3, "stale": true, "thresholdHours": 48 },
{ "key": "china_market", "ageHours": 20.7, "stale": false, "thresholdHours": 80 },
{ "key": "hsgt", "ageHours": 20.9, "stale": false, "thresholdHours": 80 },
{ "key": "ah_pairs_cnhk", "ageHours": 20.7, "stale": false, "thresholdHours": 48 },
{ "key": "ah_pairs_us", "ageHours": 8.6, "stale": false, "thresholdHours": 48 },
{ "key": "trump_intraday", "ageHours": 8.6, "stale": false, "thresholdHours": 36 },
{ "key": "factors", "ageHours": 8.6, "stale": false, "thresholdHours": 36 },
{ "key": "cn_pro", "ageHours": null, "stale": true, "thresholdHours": 36 }, // file missing
{ "key": "earnings_vol", "ageHours": 8.6, "stale": false, "thresholdHours": 36 },
{ "key": "options_history","ageHours": 8.6, "stale": false, "thresholdHours": 36 },
{ "key": "fundamentals", "ageHours": 8.7, "stale": false, "thresholdHours": 36,
"note": "5012 symbols, snapshot 2026-09-03" } // or the problem list, e.g. "index too old; 3 failed batches"
],
"flow": { "fetched_at": "2026-10-20T14:02:11.000Z", "state": "live", "age_minutes": 3.0, "market_open": true }, // Unusual Whales cache freshness (informational; not in files[]/anyStale)
"anyStale": true // overall status: true if any file is stale (โ HTTP 503)
}
| Code | Meaning |
|---|---|
| 503 | At least one file is stale (anyStale: true) โ same JSON body as the 200 response, so uptime monitors can alert on the status code alone |
anyStale: 200 only when every file is fresh, 503 otherwise. The body does not change, so consumers that parse it (the site layout banner and scripts/healthcheck_alert.py, every 30 min) still read anyStale / per-file stale.ageHours is rounded to one decimal. For AWS files the age is measured from the payload's generated_at, so a file re-synced without new content still ages.curl -H "X-API-Key: $KEY" "https://news.all-vista.org/api/health"
| Code | Meaning |
|---|---|
| 200 | Success |
| 202 | Analysis already in progress for this ID โ retry later |
| 400 | Missing or invalid required parameters |
| 401 | Unauthorized โ missing or invalid API key |
| 404 | Post/ticker not found, or no data available |
| 429 | Rate limit exceeded โ see the Retry-After header and retry_after_seconds in the body |
| 500 | Server error or LLM provider failure |
| 502 | Upstream data provider failed |
X-AI-Provider and X-AI-Model response headers naming the LLM that produced the result (for example codex / gpt-5.5), or cache / cached for cache hits.