{"openapi":"3.1.0","info":{"title":"MarketTwits News (English) — x402","version":"1.0.0","description":"Real-time English translations of MarketTwits (top Russian financial Telegram channel). Covers macro, central banks, oil/commodities, geopolitics, equities and crypto. Items are tagged high/medium importance and updated every few minutes. Ideal for trading bots and news agents. Also sells Russian market data (CBR FX and key rate, MOEX quotes/indices/movers, Rosstat fuel prices), public Telegram channel reading/search and Wildberries/Ozon product data.","x-guidance":"Twenty-seven paid endpoints via x402 (USDC, scheme exact, network eip155:8453, payTo 0x2c257EE70952a16f00c99d40fDFF2d28f1A5b8A2). Feed endpoints, $0.003 each: GET /news/latest?limit=N - full feed (high+medium), use for polling/monitoring all market news. GET /news/important?limit=N - only importance=high, use when you want market-moving headlines only. GET /news/search?q=WORDS&limit=N - case-insensitive keyword search (all words must match; '#oil' and 'oil' both work), use for a topic/ticker/country (e.g. q=oil, q=Fed rates, q=BTC). limit is 1-50 (default 20); results newest first. An unpaid call returns HTTP 402 with a PAYMENT-REQUIRED header (base64 x402 v2 challenge); pay with an x402 client (e.g. @x402/fetch) and retry. Invalid q (empty or >100 chars) returns 400 before any payment; no match returns 200 with items []. Response: {count, items:[{id, source_url, published_at, importance, text_en, posted_to_x, buffer_post_id}]}. Analytics endpoints (fixed prices): GET /news/alerts/check?q=WORDS&hours=24 ($0.004) - count of matching items in the last N hours (1-168) plus the 5 most recent, use for keyword alerts; GET /news/summary?q=WORDS&limit=10 ($0.008) - 3-5 sentence extractive English summary of the latest matching news (limit 1-50); GET /news/top-topics?hours=6 ($0.005) - top 5 hashtags/keywords in high-importance news of the last N hours (1-72; falls back to the last 20 high items, fallback=true). GET /news/summary/recent?q=WORDS&hours=12 ($0.007) - like /news/summary but only items from the last N hours (1-168, up to 50), returns {query, hours, since, count, high_count, summary, items}; GET /news/alerts/new?q=WORDS&hours=6 ($0.005) - only HIGH-importance matches in the last N hours (1-168), returns {has_new, count, latest}, use as a cheap alert poll; GET /news/topics/trending?hours=6 ($0.004) - top 5 topics in high news of the last N hours (1-72) with prev_count, change (vs. the previous equal window) and latest_id. Non-numeric hours/limit returns 400 before payment. More news endpoints: GET /news/since?id=LAST_ID&limit=50 ($0.002) - items with id > LAST_ID oldest first + next_id/has_more (cheap polling cursor); GET /news/movers?hours=6&min_pct=2 ($0.005) - top gainers/losers parsed from '#TICKER = ±X%' mentions; GET /news/country?code=RU&hours=24&importance=all ($0.004) - news about a country (flag emoji + keywords) with counts, top topics, 10 latest headlines; GET /news/data-surprises?hours=24&q=CPI ($0.006) - macro releases and earnings vs. expectations (actual, expected, previous, surprise, direction); GET /news/sentiment?q=WORDS&hours=24 ($0.005) - heuristic lexicon tone: bullish/bearish/neutral counts and score in [-1,1] (method: heuristic); GET /news/digest?hours=24 ($0.01) - sectioned briefing (central_banks, macro, energy, equities, crypto, geopolitics) with up to 5 headlines each. Russian market data: GET /ru/fx?codes=USD,EUR&date=YYYY-MM-DD ($0.0015) - official CBR rates (RUB per unit) with change vs the previous set; GET /ru/key-rate?months=24 ($0.0015) - CBR key rate, effective_since, previous rate and the list of changes; GET /moex/quote?ticker=SBER ($0.003) - Moscow Exchange quote (price, change_pct, OHLC, volume, bid/offer), delayed ~15 min; GET /moex/index?code=IMOEX ($0.003) - index level/change for up to 5 codes (IMOEX, RTSI, ...) or code=list; GET /moex/movers?limit=10 ($0.004) - top TQBR gainers/losers and breadth (previous session before the open); GET /ru/fuel?weeks=4 ($0.003) - Rosstat weekly average pump prices AI-92/95/98 and diesel (RUB/l, as_of, weekly/4-week/YTD change). Telegram: GET /tg/channel/latest?channel=NAME&limit=20 ($0.004) - newest posts of a public channel (id, date, text, views, link); GET /tg/search?q=WORDS&channels=a,b ($0.006) - keyword search across up to 5 public channels. Upstream failures return 502 and unknown ticker/index/channel 404, neither is settled; invalid parameters return 400 before payment. Marketplace endpoint: GET /product/info?url=PRODUCT_URL ($0.004) - live Wildberries (wildberries.ru/wb.ru /catalog/<id>/) or Ozon (ozon.ru /product/<slug>-<id>/) product data {source, product_id, title, price:{amount, currency:'RUB', original_amount?}, rating, reviews_count, availability, in_stock}; a bad or foreign url returns 400 before payment, and if the marketplace blocks/fails it returns 502 upstream_unavailable without settling the payment. GET /product/compare?urls=URL1,URL2[,...] ($0.006) - 2-5 products (or repeat url=): items with price/original_price/in_stock/rating, cheapest, most_expensive, price_diff {abs, percent}, in_stock_count, all_in_stock; per-item errors allowed, 502 if fewer than 2 priced. GET /product/monitor?url=URL&target_price=RUB ($0.005) - below_target (current <= target and not out of stock), current_price, diff_abs/diff_percent, in_stock; out-of-stock without a price -> 200 below_target:false current_price:null. GET /product/history?url=URL ($0.004) - Wildberries weekly CDN price points + observed + live price, min/max/avg, change_30d, history_limited when only the current price exists. Wildberries works via a headless-browser parser; Ozon is currently blocked (502, not charged). Free: GET /news/sample (one truncated item), GET /health.","contact":{"email":"whale2003@proton.me"}},"servers":[{"url":"https://x402-markettwits-news.onrender.com"}],"paths":{"/news/latest":{"get":{"operationId":"getLatestNews","summary":"Latest translated MarketTwits news (newest first)","description":"Latest translated MarketTwits news (newest first), limit 1-50","tags":["news"],"security":[],"parameters":[{"name":"limit","in":"query","required":false,"description":"Number of items (newest first)","schema":{"type":"integer","minimum":1,"maximum":50,"default":20}}],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.003"},"protocols":[{"x402":{"network":"eip155:8453","scheme":"exact","payTo":"0x2c257EE70952a16f00c99d40fDFF2d28f1A5b8A2","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","amount":"3000"}}]},"responses":{"200":{"description":"News items (newest first); empty items array when nothing matches","content":{"application/json":{"schema":{"type":"object","required":["count","items"],"properties":{"count":{"type":"integer"},"items":{"type":"array","items":{"$ref":"#/components/schemas/NewsItem"}}}}}}},"402":{"description":"Payment Required. x402 v2 challenge in the PAYMENT-REQUIRED response header (base64 JSON).","headers":{"PAYMENT-REQUIRED":{"description":"Base64-encoded x402 PaymentRequired object","schema":{"type":"string"}}}}}}},"/news/important":{"get":{"operationId":"getImportantNews","summary":"High-importance news only (newest first)","description":"Only importance=high MarketTwits news (newest first), limit 1-50","tags":["news"],"security":[],"parameters":[{"name":"limit","in":"query","required":false,"description":"Number of items (newest first)","schema":{"type":"integer","minimum":1,"maximum":50,"default":20}}],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.003"},"protocols":[{"x402":{"network":"eip155:8453","scheme":"exact","payTo":"0x2c257EE70952a16f00c99d40fDFF2d28f1A5b8A2","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","amount":"3000"}}]},"responses":{"200":{"description":"News items (newest first); empty items array when nothing matches","content":{"application/json":{"schema":{"type":"object","required":["count","items"],"properties":{"count":{"type":"integer"},"items":{"type":"array","items":{"$ref":"#/components/schemas/NewsItem"}}}}}}},"402":{"description":"Payment Required. x402 v2 challenge in the PAYMENT-REQUIRED response header (base64 JSON).","headers":{"PAYMENT-REQUIRED":{"description":"Base64-encoded x402 PaymentRequired object","schema":{"type":"string"}}}}}}},"/news/search":{"get":{"operationId":"searchNews","summary":"Keyword search in translated news (newest first)","description":"Case-insensitive keyword search in translated MarketTwits news (all words must match), limit 1-50","tags":["news"],"security":[],"parameters":[{"name":"q","in":"query","required":true,"description":"Keywords (case-insensitive). Several words = all must match. Hashtags match with or without '#', e.g. 'oil', '#Fed rates'.","schema":{"type":"string","minLength":1,"maxLength":100}},{"name":"limit","in":"query","required":false,"description":"Number of items (newest first)","schema":{"type":"integer","minimum":1,"maximum":50,"default":20}}],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.003"},"protocols":[{"x402":{"network":"eip155:8453","scheme":"exact","payTo":"0x2c257EE70952a16f00c99d40fDFF2d28f1A5b8A2","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","amount":"3000"}}]},"responses":{"200":{"description":"News items (newest first); empty items array when nothing matches","content":{"application/json":{"schema":{"type":"object","required":["count","items"],"properties":{"count":{"type":"integer"},"items":{"type":"array","items":{"$ref":"#/components/schemas/NewsItem"}}}}}}},"400":{"description":"Missing or invalid q (1-100 chars). Returned before payment when a payment is attached or a parameter is invalid.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"402":{"description":"Payment Required. x402 v2 challenge in the PAYMENT-REQUIRED response header (base64 JSON).","headers":{"PAYMENT-REQUIRED":{"description":"Base64-encoded x402 PaymentRequired object","schema":{"type":"string"}}}}}}},"/news/alerts/check":{"get":{"operationId":"checkNewsAlert","summary":"Keyword alert check: how many matching items in the last N hours","description":"Count of news matching q (same matching as /news/search) published in the last N hours (1-168, default 24), plus the 5 most recent","tags":["news"],"security":[],"parameters":[{"name":"q","in":"query","required":true,"description":"Keywords (case-insensitive). Several words = all must match. Hashtags match with or without '#', e.g. 'oil', '#Fed rates'.","schema":{"type":"string","minLength":1,"maxLength":100}},{"name":"hours","in":"query","required":false,"description":"Look-back window in hours (default 24, clamped to 1-168)","schema":{"type":"integer","minimum":1,"maximum":168,"default":24}}],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.004"},"protocols":[{"x402":{"network":"eip155:8453","scheme":"exact","payTo":"0x2c257EE70952a16f00c99d40fDFF2d28f1A5b8A2","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","amount":"4000"}}]},"responses":{"200":{"description":"Alert check result (count 0 and items [] when nothing matched)","content":{"application/json":{"schema":{"type":"object","required":["query","hours","count","since","latest_id","latest_published_at","items"],"properties":{"query":{"type":"string"},"hours":{"type":"integer","description":"Window actually used (1-168)"},"count":{"type":"integer","description":"Matching items published within the window"},"since":{"type":"string","format":"date-time","description":"Window start (now - hours)"},"latest_id":{"type":["integer","null"]},"latest_published_at":{"type":["string","null"],"format":"date-time"},"items":{"type":"array","maxItems":5,"items":{"type":"object","required":["id","published_at","importance","source_url","text_en"],"properties":{"id":{"type":"integer","description":"Telegram post id in t.me/markettwits","examples":[389638]},"published_at":{"type":"string","format":"date-time","description":"Publication time of the original post (ISO 8601)"},"importance":{"type":"string","enum":["high","medium","low"]},"source_url":{"type":"string","format":"uri","description":"Original Russian post"},"text_en":{"type":"string","description":"English translation of the post"}}},"description":"Up to 5 most recent matching items in the window"}}}}}},"400":{"description":"Missing or invalid q (1-100 chars) or non-numeric hours. Returned before payment when a payment is attached or a parameter is invalid.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"402":{"description":"Payment Required. x402 v2 challenge in the PAYMENT-REQUIRED response header (base64 JSON).","headers":{"PAYMENT-REQUIRED":{"description":"Base64-encoded x402 PaymentRequired object","schema":{"type":"string"}}}}}}},"/news/summary":{"get":{"operationId":"summarizeNews","summary":"Short extractive English summary of the latest news on a keyword","description":"3-5 sentence extractive summary of the latest news matching q (limit 1-50, default 10): lead sentence + de-duplicated headlines, high-importance first","tags":["news"],"security":[],"parameters":[{"name":"q","in":"query","required":true,"description":"Keywords (case-insensitive). Several words = all must match. Hashtags match with or without '#', e.g. 'oil', '#Fed rates'.","schema":{"type":"string","minLength":1,"maxLength":100}},{"name":"limit","in":"query","required":false,"description":"Number of latest matching items to summarize (default 10, max 50)","schema":{"type":"integer","minimum":1,"maximum":50,"default":10}}],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.008"},"protocols":[{"x402":{"network":"eip155:8453","scheme":"exact","payTo":"0x2c257EE70952a16f00c99d40fDFF2d28f1A5b8A2","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","amount":"8000"}}]},"responses":{"200":{"description":"Summary (count 0 and a 'No recent news matched' summary when nothing matched)","content":{"application/json":{"schema":{"type":"object","required":["query","count","summary","items"],"properties":{"query":{"type":"string"},"count":{"type":"integer","description":"Number of matching items summarized"},"summary":{"type":"string","description":"Extractive English summary, 3-5 sentences (lead + de-duplicated headlines)"},"items":{"type":"array","items":{"type":"object","required":["id","published_at","importance","source_url"],"properties":{"id":{"type":"integer","description":"Telegram post id in t.me/markettwits","examples":[389638]},"published_at":{"type":"string","format":"date-time","description":"Publication time of the original post (ISO 8601)"},"importance":{"type":"string","enum":["high","medium","low"]},"source_url":{"type":"string","format":"uri","description":"Original Russian post"}}}}}}}}},"400":{"description":"Missing or invalid q (1-100 chars) or non-numeric limit. Returned before payment when a payment is attached or a parameter is invalid.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"402":{"description":"Payment Required. x402 v2 challenge in the PAYMENT-REQUIRED response header (base64 JSON).","headers":{"PAYMENT-REQUIRED":{"description":"Base64-encoded x402 PaymentRequired object","schema":{"type":"string"}}}}}}},"/news/top-topics":{"get":{"operationId":"getTopTopics","summary":"Top 5 keywords/hashtags in high-importance news of the last N hours","description":"Top 5 topics (hashtags, names, keywords; counted once per item) across high-importance news of the last N hours (1-72, default 6)","tags":["news"],"security":[],"parameters":[{"name":"hours","in":"query","required":false,"description":"Look-back window in hours (default 6, clamped to 1-72)","schema":{"type":"integer","minimum":1,"maximum":72,"default":6}}],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.005"},"protocols":[{"x402":{"network":"eip155:8453","scheme":"exact","payTo":"0x2c257EE70952a16f00c99d40fDFF2d28f1A5b8A2","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","amount":"5000"}}]},"responses":{"200":{"description":"Top topics","content":{"application/json":{"schema":{"type":"object","required":["hours","items_considered","topics","fallback"],"properties":{"hours":{"type":"integer","description":"Window actually used (1-72)"},"items_considered":{"type":"integer","description":"High-importance items analysed"},"topics":{"type":"array","maxItems":5,"items":{"type":"object","required":["topic","count"],"properties":{"topic":{"type":"string"},"count":{"type":"integer","description":"Number of items mentioning the topic"}}}},"fallback":{"type":"boolean","description":"true when no high item fell in the window and the last 20 high items were used"},"note":{"type":"string","description":"Explanation when fallback is true"}}}}}},"400":{"description":"hours is not a number. Returned before payment.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"402":{"description":"Payment Required. x402 v2 challenge in the PAYMENT-REQUIRED response header (base64 JSON).","headers":{"PAYMENT-REQUIRED":{"description":"Base64-encoded x402 PaymentRequired object","schema":{"type":"string"}}}}}}},"/news/summary/recent":{"get":{"operationId":"summarizeRecentNews","summary":"Extractive English summary of news on a keyword from the last N hours","description":"3-5 sentence extractive summary of news matching q published in the last N hours (1-168, default 12; up to 50 items), with high_count. Use for 'what happened with X today'.","tags":["news"],"security":[],"parameters":[{"name":"q","in":"query","required":true,"description":"Keywords (case-insensitive). Several words = all must match. Hashtags match with or without '#', e.g. 'oil', '#Fed rates'.","schema":{"type":"string","minLength":1,"maxLength":100}},{"name":"hours","in":"query","required":false,"description":"Look-back window in hours (default 12, clamped to 1-168)","schema":{"type":"integer","minimum":1,"maximum":168,"default":12}}],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.007"},"protocols":[{"x402":{"network":"eip155:8453","scheme":"exact","payTo":"0x2c257EE70952a16f00c99d40fDFF2d28f1A5b8A2","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","amount":"7000"}}]},"responses":{"200":{"description":"Summary of the window (count 0 and 'No news matched \"q\" in the last N hours.' when nothing matched)","content":{"application/json":{"schema":{"type":"object","required":["query","hours","since","count","high_count","summary","items"],"properties":{"query":{"type":"string"},"hours":{"type":"integer","description":"Window actually used (1-168)"},"since":{"type":"string","format":"date-time","description":"Window start (now - hours)"},"count":{"type":"integer","description":"Matching items in the window that were summarized (max 50)"},"high_count":{"type":"integer","description":"How many of them are importance=high"},"summary":{"type":"string","description":"Extractive English summary, 3-5 sentences; 'No news matched \"q\" in the last N hours.' when count is 0"},"items":{"type":"array","maxItems":50,"items":{"type":"object","required":["id","published_at","importance","source_url"],"properties":{"id":{"type":"integer","description":"Telegram post id in t.me/markettwits","examples":[389638]},"published_at":{"type":"string","format":"date-time","description":"Publication time of the original post (ISO 8601)"},"importance":{"type":"string","enum":["high","medium","low"]},"source_url":{"type":"string","format":"uri","description":"Original Russian post"}}}}}}}}},"400":{"description":"Missing or invalid q (1-100 chars) or non-numeric hours. Returned before payment when a payment is attached or a parameter is invalid.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"402":{"description":"Payment Required. x402 v2 challenge in the PAYMENT-REQUIRED response header (base64 JSON).","headers":{"PAYMENT-REQUIRED":{"description":"Base64-encoded x402 PaymentRequired object","schema":{"type":"string"}}}}}}},"/news/alerts/new":{"get":{"operationId":"checkNewHighAlert","summary":"Is there new HIGH-importance news on a keyword in the last N hours?","description":"Checks only importance=high news matching q in the last N hours (1-168, default 6): has_new, count and the latest item. Cheap poll for market-moving alerts on a topic/ticker.","tags":["news"],"security":[],"parameters":[{"name":"q","in":"query","required":true,"description":"Keywords (case-insensitive). Several words = all must match. Hashtags match with or without '#', e.g. 'oil', '#Fed rates'.","schema":{"type":"string","minLength":1,"maxLength":100}},{"name":"hours","in":"query","required":false,"description":"Look-back window in hours (default 6, clamped to 1-168)","schema":{"type":"integer","minimum":1,"maximum":168,"default":6}}],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.005"},"protocols":[{"x402":{"network":"eip155:8453","scheme":"exact","payTo":"0x2c257EE70952a16f00c99d40fDFF2d28f1A5b8A2","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","amount":"5000"}}]},"responses":{"200":{"description":"Alert result (has_new false, count 0, latest null when nothing matched)","content":{"application/json":{"schema":{"type":"object","required":["query","hours","since","has_new","count","latest"],"properties":{"query":{"type":"string"},"hours":{"type":"integer","description":"Window actually used (1-168)"},"since":{"type":"string","format":"date-time","description":"Window start (now - hours)"},"has_new":{"type":"boolean","description":"true when at least one HIGH-importance item matched q in the window"},"count":{"type":"integer","description":"Number of matching HIGH-importance items in the window"},"latest":{"oneOf":[{"type":"object","required":["id","published_at","text_en","source_url"],"properties":{"id":{"type":"integer","description":"Telegram post id in t.me/markettwits","examples":[389638]},"published_at":{"type":"string","format":"date-time","description":"Publication time of the original post (ISO 8601)"},"text_en":{"type":"string","description":"English translation of the post"},"source_url":{"type":"string","format":"uri","description":"Original Russian post"}}},{"type":"null"}],"description":"Most recent matching HIGH item, or null"}}}}}},"400":{"description":"Missing or invalid q (1-100 chars) or non-numeric hours. Returned before payment when a payment is attached or a parameter is invalid.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"402":{"description":"Payment Required. x402 v2 challenge in the PAYMENT-REQUIRED response header (base64 JSON).","headers":{"PAYMENT-REQUIRED":{"description":"Base64-encoded x402 PaymentRequired object","schema":{"type":"string"}}}}}}},"/news/topics/trending":{"get":{"operationId":"getTrendingTopics","summary":"Trending topics in high-importance news with change vs. the previous window","description":"Top 5 topics (hashtags, names, keywords; counted once per item) in high-importance news of the last N hours (1-72, default 6), each with prev_count in the previous equal-length window, change = count - prev_count, and latest_id/latest_source_url","tags":["news"],"security":[],"parameters":[{"name":"hours","in":"query","required":false,"description":"Look-back window in hours (default 6, clamped to 1-72)","schema":{"type":"integer","minimum":1,"maximum":72,"default":6}}],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.004"},"protocols":[{"x402":{"network":"eip155:8453","scheme":"exact","payTo":"0x2c257EE70952a16f00c99d40fDFF2d28f1A5b8A2","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","amount":"4000"}}]},"responses":{"200":{"description":"Trending topics","content":{"application/json":{"schema":{"type":"object","required":["hours","items_considered","fallback","topics"],"properties":{"hours":{"type":"integer","description":"Window actually used (1-72)"},"items_considered":{"type":"integer","description":"High-importance items analysed in the current window"},"fallback":{"type":"boolean","description":"true when no high item fell in the window: the last 20 high items were used and compared with the 20 before them"},"note":{"type":"string","description":"Explanation when fallback is true"},"topics":{"type":"array","maxItems":5,"items":{"type":"object","required":["topic","count","prev_count","change","latest_id"],"properties":{"topic":{"type":"string"},"count":{"type":"integer","description":"Items mentioning the topic in the last N hours"},"prev_count":{"type":"integer","description":"Items mentioning it in the previous window of equal length"},"change":{"type":"integer","description":"count - prev_count (positive = rising)"},"latest_id":{"type":"integer","description":"id of the newest item mentioning the topic"},"latest_source_url":{"type":"string","format":"uri","description":"Source URL of that item"}}}}}}}}},"400":{"description":"hours is not a number. Returned before payment.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"402":{"description":"Payment Required. x402 v2 challenge in the PAYMENT-REQUIRED response header (base64 JSON).","headers":{"PAYMENT-REQUIRED":{"description":"Base64-encoded x402 PaymentRequired object","schema":{"type":"string"}}}}}}},"/news/since":{"get":{"operationId":"getNewsSince","summary":"Incremental feed: items newer than the id you already have (cursor polling)","description":"All stored items with id > id (oldest first, up to limit 1-100, default 50) plus next_id/has_more for the next call. The cheapest way for a bot to poll without duplicates: keep next_id and pass it back.","tags":["news"],"security":[],"parameters":[{"name":"id","in":"query","required":true,"description":"Last item id you already have (0 = from the oldest stored item). Items with a larger id are returned, oldest first.","schema":{"type":"string","pattern":"^[0-9]{1,15}$"}},{"name":"limit","in":"query","required":false,"description":"Max items per page (default 50, max 100)","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}}],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.002"},"protocols":[{"x402":{"network":"eip155:8453","scheme":"exact","payTo":"0x2c257EE70952a16f00c99d40fDFF2d28f1A5b8A2","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","amount":"2000"}}]},"responses":{"200":{"description":"Items newer than id (count 0 and next_id = id when nothing new)","content":{"application/json":{"schema":{"type":"object","required":["since_id","count","has_more","next_id","items"],"properties":{"since_id":{"type":"integer"},"count":{"type":"integer"},"has_more":{"type":"boolean","description":"More items after this page: call again with id=next_id"},"next_id":{"type":"integer","description":"Pass as id= on the next call (= since_id when nothing new)"},"latest_id":{"type":["integer","null"],"description":"Newest id in the store"},"items":{"type":"array","items":{"type":"object","required":["id","source_url","published_at","importance","text_en"],"properties":{"id":{"type":"integer","description":"Telegram post id in t.me/markettwits","examples":[389638]},"source_url":{"type":"string","format":"uri","description":"Original Russian post"},"published_at":{"type":"string","format":"date-time","description":"Publication time of the original post (ISO 8601)"},"importance":{"type":"string","enum":["high","medium","low"]},"text_en":{"type":"string","description":"English translation of the post"},"posted_to_x":{"type":"boolean","description":"Whether the item was also posted to X"},"buffer_post_id":{"type":["string","null"],"description":"Buffer post id when posted to X, else null"}}},"description":"Oldest first"}}}}}},"400":{"description":"id missing (with a payment attached) or not a non-negative integer, or limit not a number. Returned before payment.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"402":{"description":"Payment Required. x402 v2 challenge in the PAYMENT-REQUIRED response header (base64 JSON).","headers":{"PAYMENT-REQUIRED":{"description":"Base64-encoded x402 PaymentRequired object","schema":{"type":"string"}}}}}}},"/news/movers":{"get":{"operationId":"getNewsMovers","summary":"Top gainers/losers reported in the news ('#TICKER = ±X%')","description":"Parses '#TICKER [Name] = ±X%' price-move mentions (stocks, indices, crypto; RU/US/... from the flag) in news of the last N hours (1-72, default 6), newest mention per ticker, |move| >= min_pct (default 0): top 10 gainers and top 10 losers with the source item.","tags":["news"],"security":[],"parameters":[{"name":"hours","in":"query","required":false,"description":"Look-back window in hours (default 6, clamped to 1-72)","schema":{"type":"integer","minimum":1,"maximum":72,"default":6}},{"name":"min_pct","in":"query","required":false,"description":"Minimum absolute move in percent (default 0, max 100), e.g. 3 or 2.5","schema":{"type":"string","pattern":"^[0-9]+([.,][0-9]+)?$","default":"0"}}],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.005"},"protocols":[{"x402":{"network":"eip155:8453","scheme":"exact","payTo":"0x2c257EE70952a16f00c99d40fDFF2d28f1A5b8A2","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","amount":"5000"}}]},"responses":{"200":{"description":"Movers (empty arrays when no moves were reported)","content":{"application/json":{"schema":{"type":"object","required":["hours","min_pct","since","tickers_found","gainers","losers"],"properties":{"hours":{"type":"integer"},"min_pct":{"type":"number"},"since":{"type":"string","format":"date-time"},"tickers_found":{"type":"integer","description":"Distinct tickers with a '#TICKER = ±X%' mention in the window (newest mention per ticker)"},"gainers":{"type":"array","items":{"type":"object","required":["ticker","pct","id","published_at"],"properties":{"ticker":{"type":"string"},"name":{"type":["string","null"]},"pct":{"type":"number","description":"Reported move in percent (signed)"},"country":{"type":["string","null"],"description":"ISO code from the flag before the ticker"},"id":{"type":"integer"},"published_at":{"type":"string","format":"date-time"},"importance":{"type":"string"},"source_url":{"type":"string","format":"uri"},"headline":{"type":"string"}}},"description":"Top 10, largest first"},"losers":{"type":"array","items":{"type":"object","required":["ticker","pct","id","published_at"],"properties":{"ticker":{"type":"string"},"name":{"type":["string","null"]},"pct":{"type":"number","description":"Reported move in percent (signed)"},"country":{"type":["string","null"],"description":"ISO code from the flag before the ticker"},"id":{"type":"integer"},"published_at":{"type":"string","format":"date-time"},"importance":{"type":"string"},"source_url":{"type":"string","format":"uri"},"headline":{"type":"string"}}},"description":"Top 10, most negative first"}}}}}},"400":{"description":"hours or min_pct is not a number. Returned before payment.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"402":{"description":"Payment Required. x402 v2 challenge in the PAYMENT-REQUIRED response header (base64 JSON).","headers":{"PAYMENT-REQUIRED":{"description":"Base64-encoded x402 PaymentRequired object","schema":{"type":"string"}}}}}}},"/news/country":{"get":{"operationId":"getCountryNews","summary":"News about one country (flag emoji + country keywords) with counts and top topics","description":"Items of the last N hours (1-168, default 24; importance all|high|medium|low) that carry the country's flag emoji or mention it (e.g. RU: Russia/Kremlin/Bank of Russia/MOEX; US: USA/Fed/White House): count, high_count, share_of_window, top_topics and the 10 latest headlines.","tags":["news"],"security":[],"parameters":[{"name":"code","in":"query","required":true,"description":"ISO 3166-1 alpha-2 country code (e.g. US, RU, CN, UA, IR, GB; UK = GB; EU accepted)","schema":{"type":"string","pattern":"^[A-Za-z]{2}$"}},{"name":"hours","in":"query","required":false,"description":"Look-back window in hours (default 24, clamped to 1-168)","schema":{"type":"integer","minimum":1,"maximum":168,"default":24}},{"name":"importance","in":"query","required":false,"description":"Importance filter (default all)","schema":{"type":"string","enum":["all","high","medium","low"],"default":"all"}}],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.004"},"protocols":[{"x402":{"network":"eip155:8453","scheme":"exact","payTo":"0x2c257EE70952a16f00c99d40fDFF2d28f1A5b8A2","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","amount":"4000"}}]},"responses":{"200":{"description":"Country news (count 0 when nothing matched)","content":{"application/json":{"schema":{"type":"object","required":["code","hours","count","high_count","latest","top_topics"],"properties":{"code":{"type":"string"},"flag":{"type":["string","null"]},"hours":{"type":"integer"},"importance":{"type":"string"},"since":{"type":"string","format":"date-time"},"count":{"type":"integer"},"high_count":{"type":"integer"},"by_flag":{"type":"integer","description":"Matches by flag emoji (the rest by country keywords)"},"share_of_window":{"type":"number","description":"Percent of all items in the window"},"top_topics":{"type":"array","items":{"type":"object","properties":{"topic":{"type":"string"},"count":{"type":"integer"}}}},"latest":{"type":"array","items":{"type":"object","required":["id","published_at","importance","headline","source_url"],"properties":{"id":{"type":"integer","description":"Telegram post id in t.me/markettwits","examples":[389638]},"published_at":{"type":"string","format":"date-time","description":"Publication time of the original post (ISO 8601)"},"importance":{"type":"string","enum":["high","medium","low"]},"source_url":{"type":"string","format":"uri","description":"Original Russian post"},"headline":{"type":"string","description":"First meaningful line, emoji removed"}}},"description":"Up to 10, newest first"}}}}}},"400":{"description":"code is not a 2-letter country code, importance not all|high|medium|low, or hours not a number. Returned before payment.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"402":{"description":"Payment Required. x402 v2 challenge in the PAYMENT-REQUIRED response header (base64 JSON).","headers":{"PAYMENT-REQUIRED":{"description":"Base64-encoded x402 PaymentRequired object","schema":{"type":"string"}}}}}}},"/news/data-surprises":{"get":{"operationId":"getDataSurprises","summary":"Macro data and earnings vs. expectations: actual, expected, previous, surprise","description":"Parses releases like 'US Pending Home Sales (Sep) = -7.3% m/m (exp. -0.5% / prev. +0.3%)' and earnings lines like '3Q REV. $14.58B, EST. $12.87B' from news of the last N hours (1-168, default 24; optional q filter): indicator, actual, expected, previous, unit, surprise (actual - expected), surprise_pct and direction above/below/inline.","tags":["news"],"security":[],"parameters":[{"name":"hours","in":"query","required":false,"description":"Look-back window in hours (default 24, clamped to 1-168)","schema":{"type":"integer","minimum":1,"maximum":168,"default":24}},{"name":"q","in":"query","required":false,"description":"Optional keyword filter (same matching as /news/search)","schema":{"type":"string","minLength":1,"maxLength":100}}],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.006"},"protocols":[{"x402":{"network":"eip155:8453","scheme":"exact","payTo":"0x2c257EE70952a16f00c99d40fDFF2d28f1A5b8A2","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","amount":"6000"}}]},"responses":{"200":{"description":"Parsed surprises (count 0 when none)","content":{"application/json":{"schema":{"type":"object","required":["hours","count","above","below","items"],"properties":{"hours":{"type":"integer"},"query":{"type":["string","null"]},"since":{"type":"string","format":"date-time"},"count":{"type":"integer"},"above":{"type":"integer"},"below":{"type":"integer"},"items":{"type":"array","items":{"type":"object","required":["kind","indicator","actual","expected","surprise","direction","id"],"properties":{"kind":{"type":"string","enum":["macro","earnings"]},"indicator":{"type":"string"},"ticker":{"type":"string"},"actual":{"type":"number"},"expected":{"type":"number"},"previous":{"type":["number","null"]},"unit":{"type":["string","null"],"description":"%, M, B, K, $, '% m/m' ..."},"surprise":{"type":"number","description":"actual - expected (same unit)"},"surprise_pct":{"type":["number","null"],"description":"surprise / |expected| * 100"},"direction":{"type":"string","enum":["above","below","inline"]},"id":{"type":"integer"},"published_at":{"type":"string","format":"date-time"},"importance":{"type":"string"},"source_url":{"type":"string","format":"uri"}}},"description":"Newest first, max 50"}}}}}},"400":{"description":"hours is not a number, or q is present but empty/longer than 100 chars. Returned before payment.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"402":{"description":"Payment Required. x402 v2 challenge in the PAYMENT-REQUIRED response header (base64 JSON).","headers":{"PAYMENT-REQUIRED":{"description":"Base64-encoded x402 PaymentRequired object","schema":{"type":"string"}}}}}}},"/news/sentiment":{"get":{"operationId":"getNewsSentiment","summary":"Heuristic bullish/bearish tone of news on a keyword (lexicon, not a model)","description":"Scores each item matching q in the last N hours (1-168, default 24) with a keyword/emoji lexicon (rise/beat/upgrade vs. fall/miss/sanctions, ⬆️/⬇️) plus explicit '= ±X%' moves, and returns bullish/bearish/neutral counts, score = (bullish - bearish)/count in [-1, 1], a label and examples. method is always 'heuristic'.","tags":["news"],"security":[],"parameters":[{"name":"q","in":"query","required":true,"description":"Keywords (case-insensitive). Several words = all must match. Hashtags match with or without '#', e.g. 'oil', '#Fed rates'.","schema":{"type":"string","minLength":1,"maxLength":100}},{"name":"hours","in":"query","required":false,"description":"Look-back window in hours (default 24, clamped to 1-168)","schema":{"type":"integer","minimum":1,"maximum":168,"default":24}}],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.005"},"protocols":[{"x402":{"network":"eip155:8453","scheme":"exact","payTo":"0x2c257EE70952a16f00c99d40fDFF2d28f1A5b8A2","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","amount":"5000"}}]},"responses":{"200":{"description":"Sentiment (label no_data when nothing matched)","content":{"application/json":{"schema":{"type":"object","required":["query","hours","count","bullish","bearish","neutral","score","label","method"],"properties":{"query":{"type":"string"},"hours":{"type":"integer"},"since":{"type":"string","format":"date-time"},"count":{"type":"integer"},"bullish":{"type":"integer"},"bearish":{"type":"integer"},"neutral":{"type":"integer"},"score":{"type":"number","minimum":-1,"maximum":1,"description":"(bullish - bearish) / count"},"label":{"type":"string","enum":["bullish","bearish","neutral","no_data"]},"method":{"type":"string","enum":["heuristic"]},"note":{"type":"string"},"examples":{"type":"object","properties":{"bullish":{"type":"array","items":{"type":"object","required":["id","published_at","importance","headline","source_url"],"properties":{"id":{"type":"integer","description":"Telegram post id in t.me/markettwits","examples":[389638]},"published_at":{"type":"string","format":"date-time","description":"Publication time of the original post (ISO 8601)"},"importance":{"type":"string","enum":["high","medium","low"]},"source_url":{"type":"string","format":"uri","description":"Original Russian post"},"headline":{"type":"string","description":"First meaningful line, emoji removed"},"score":{"type":"number"}}}},"bearish":{"type":"array","items":{"type":"object","required":["id","published_at","importance","headline","source_url"],"properties":{"id":{"type":"integer","description":"Telegram post id in t.me/markettwits","examples":[389638]},"published_at":{"type":"string","format":"date-time","description":"Publication time of the original post (ISO 8601)"},"importance":{"type":"string","enum":["high","medium","low"]},"source_url":{"type":"string","format":"uri","description":"Original Russian post"},"headline":{"type":"string","description":"First meaningful line, emoji removed"},"score":{"type":"number"}}}}}}}}}}},"400":{"description":"Missing or invalid q (1-100 chars) or non-numeric hours. Returned before payment when a payment is attached or a parameter is invalid.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"402":{"description":"Payment Required. x402 v2 challenge in the PAYMENT-REQUIRED response header (base64 JSON).","headers":{"PAYMENT-REQUIRED":{"description":"Base64-encoded x402 PaymentRequired object","schema":{"type":"string"}}}}}}},"/news/digest":{"get":{"operationId":"getNewsDigest","summary":"Sectioned briefing: central banks, macro, energy, equities, crypto, geopolitics","description":"Groups news of the last N hours (1-48, default 24) into central_banks, macro, energy, equities, crypto and geopolitics by keyword rules (an item may appear in several), each with count, high_count and up to 5 headlines (high first, then newest), plus top_topics of high items.","tags":["news"],"security":[],"parameters":[{"name":"hours","in":"query","required":false,"description":"Look-back window in hours (default 24, clamped to 1-48)","schema":{"type":"integer","minimum":1,"maximum":48,"default":24}}],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.01"},"protocols":[{"x402":{"network":"eip155:8453","scheme":"exact","payTo":"0x2c257EE70952a16f00c99d40fDFF2d28f1A5b8A2","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","amount":"10000"}}]},"responses":{"200":{"description":"Digest","content":{"application/json":{"schema":{"type":"object","required":["hours","count","sections","top_topics"],"properties":{"hours":{"type":"integer"},"since":{"type":"string","format":"date-time"},"count":{"type":"integer"},"high_count":{"type":"integer"},"sections":{"type":"object","properties":{"central_banks":{"type":"object","properties":{"count":{"type":"integer"},"high_count":{"type":"integer"},"items":{"type":"array","items":{"type":"object","required":["id","published_at","importance","headline","source_url"],"properties":{"id":{"type":"integer","description":"Telegram post id in t.me/markettwits","examples":[389638]},"published_at":{"type":"string","format":"date-time","description":"Publication time of the original post (ISO 8601)"},"importance":{"type":"string","enum":["high","medium","low"]},"source_url":{"type":"string","format":"uri","description":"Original Russian post"},"headline":{"type":"string","description":"First meaningful line, emoji removed"}}}}}},"macro":{"type":"object","properties":{"count":{"type":"integer"},"high_count":{"type":"integer"},"items":{"type":"array","items":{"type":"object","required":["id","published_at","importance","headline","source_url"],"properties":{"id":{"type":"integer","description":"Telegram post id in t.me/markettwits","examples":[389638]},"published_at":{"type":"string","format":"date-time","description":"Publication time of the original post (ISO 8601)"},"importance":{"type":"string","enum":["high","medium","low"]},"source_url":{"type":"string","format":"uri","description":"Original Russian post"},"headline":{"type":"string","description":"First meaningful line, emoji removed"}}}}}},"energy":{"type":"object","properties":{"count":{"type":"integer"},"high_count":{"type":"integer"},"items":{"type":"array","items":{"type":"object","required":["id","published_at","importance","headline","source_url"],"properties":{"id":{"type":"integer","description":"Telegram post id in t.me/markettwits","examples":[389638]},"published_at":{"type":"string","format":"date-time","description":"Publication time of the original post (ISO 8601)"},"importance":{"type":"string","enum":["high","medium","low"]},"source_url":{"type":"string","format":"uri","description":"Original Russian post"},"headline":{"type":"string","description":"First meaningful line, emoji removed"}}}}}},"equities":{"type":"object","properties":{"count":{"type":"integer"},"high_count":{"type":"integer"},"items":{"type":"array","items":{"type":"object","required":["id","published_at","importance","headline","source_url"],"properties":{"id":{"type":"integer","description":"Telegram post id in t.me/markettwits","examples":[389638]},"published_at":{"type":"string","format":"date-time","description":"Publication time of the original post (ISO 8601)"},"importance":{"type":"string","enum":["high","medium","low"]},"source_url":{"type":"string","format":"uri","description":"Original Russian post"},"headline":{"type":"string","description":"First meaningful line, emoji removed"}}}}}},"crypto":{"type":"object","properties":{"count":{"type":"integer"},"high_count":{"type":"integer"},"items":{"type":"array","items":{"type":"object","required":["id","published_at","importance","headline","source_url"],"properties":{"id":{"type":"integer","description":"Telegram post id in t.me/markettwits","examples":[389638]},"published_at":{"type":"string","format":"date-time","description":"Publication time of the original post (ISO 8601)"},"importance":{"type":"string","enum":["high","medium","low"]},"source_url":{"type":"string","format":"uri","description":"Original Russian post"},"headline":{"type":"string","description":"First meaningful line, emoji removed"}}}}}},"geopolitics":{"type":"object","properties":{"count":{"type":"integer"},"high_count":{"type":"integer"},"items":{"type":"array","items":{"type":"object","required":["id","published_at","importance","headline","source_url"],"properties":{"id":{"type":"integer","description":"Telegram post id in t.me/markettwits","examples":[389638]},"published_at":{"type":"string","format":"date-time","description":"Publication time of the original post (ISO 8601)"},"importance":{"type":"string","enum":["high","medium","low"]},"source_url":{"type":"string","format":"uri","description":"Original Russian post"},"headline":{"type":"string","description":"First meaningful line, emoji removed"}}}}}}}},"unclassified_count":{"type":"integer"},"top_topics":{"type":"array","items":{"type":"object","properties":{"topic":{"type":"string"},"count":{"type":"integer"}}}},"note":{"type":"string"}}}}}},"400":{"description":"hours is not a number. Returned before payment.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"402":{"description":"Payment Required. x402 v2 challenge in the PAYMENT-REQUIRED response header (base64 JSON).","headers":{"PAYMENT-REQUIRED":{"description":"Base64-encoded x402 PaymentRequired object","schema":{"type":"string"}}}}}}},"/ru/fx":{"get":{"operationId":"getCbrFxRates","summary":"Official Bank of Russia FX rates (RUB) with day-over-day change","description":"CBR official exchange rates from cbr.ru XML_daily.asp for a date (default: the latest set) and optional currency codes: per currency nominal, value (RUB per nominal), per_unit (RUB per 1 unit), previous set's per_unit, change and change_pct. Cached 30 min (past dates 7 days).","tags":["ru-data"],"security":[],"parameters":[{"name":"date","in":"query","required":false,"description":"Rates date YYYY-MM-DD (default: latest set by CBR; 1992-07-01 .. tomorrow)","schema":{"type":"string","format":"date"}},{"name":"codes","in":"query","required":false,"description":"Comma-separated ISO currency codes (default: all ~55 CBR currencies), e.g. USD,EUR,CNY","schema":{"type":"string","pattern":"^[A-Za-z]{3}(,[A-Za-z]{3}){0,29}$"}}],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.0015"},"protocols":[{"x402":{"network":"eip155:8453","scheme":"exact","payTo":"0x2c257EE70952a16f00c99d40fDFF2d28f1A5b8A2","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","amount":"1500"}}]},"responses":{"200":{"description":"CBR rates","content":{"application/json":{"schema":{"type":"object","required":["base","date","count","rates"],"properties":{"source":{"type":"string"},"via":{"type":"string","enum":["direct","proxy"]},"cached":{"type":"boolean"},"stale":{"type":"boolean","description":"true when the upstream failed and a recent cached copy was served"},"fetched_at":{"type":"string","format":"date-time"},"base":{"type":"string","enum":["RUB"]},"date":{"type":"string","format":"date","description":"Date the official rates are set for"},"requested_date":{"type":["string","null"]},"previous_date":{"type":["string","null"]},"count":{"type":"integer"},"rates":{"type":"array","items":{"type":"object","required":["code","nominal","value","per_unit"],"properties":{"code":{"type":"string"},"name":{"type":["string","null"]},"nominal":{"type":"integer"},"value":{"type":"number","description":"RUB per `nominal` units"},"per_unit":{"type":"number","description":"RUB per 1 unit"},"prev_per_unit":{"type":["number","null"]},"change":{"type":["number","null"]},"change_pct":{"type":["number","null"]}}}},"missing":{"type":"array","items":{"type":"string"},"description":"Requested codes CBR does not quote"},"note":{"type":"string"}}}}}},"400":{"description":"date is not YYYY-MM-DD in 1992-07-01..tomorrow, or codes is not a comma list of 3-letter codes (max 30). Returned before payment.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"402":{"description":"Payment Required. x402 v2 challenge in the PAYMENT-REQUIRED response header (base64 JSON).","headers":{"PAYMENT-REQUIRED":{"description":"Base64-encoded x402 PaymentRequired object","schema":{"type":"string"}}}},"502":{"description":"cbr.ru unreachable or returned an unexpected response. The x402 payment is not settled.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","enum":["upstream_unavailable"]},"detail":{"type":"string"}}}}}}}}},"/ru/key-rate":{"get":{"operationId":"getCbrKeyRate","summary":"Bank of Russia key rate: current level, since when, and recent changes","description":"Current CBR key rate (% p.a.) from the cbr.ru DailyInfo web service (KeyRateXML; the hd_base/KeyRate page as fallback): rate, as_of, effective_since, previous_rate, last_change_bp and every change in the last `months` (default 24) newest first, plus min/max in the window. Cached 3 h.","tags":["ru-data"],"security":[],"parameters":[{"name":"months","in":"query","required":false,"description":"History window in months for `changes` (default 24, max 120)","schema":{"type":"integer","minimum":1,"maximum":120,"default":24}}],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.0015"},"protocols":[{"x402":{"network":"eip155:8453","scheme":"exact","payTo":"0x2c257EE70952a16f00c99d40fDFF2d28f1A5b8A2","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","amount":"1500"}}]},"responses":{"200":{"description":"Key rate","content":{"application/json":{"schema":{"type":"object","required":["rate","as_of","changes"],"properties":{"source":{"type":"string"},"via":{"type":"string","enum":["direct","proxy"]},"cached":{"type":"boolean"},"stale":{"type":"boolean","description":"true when the upstream failed and a recent cached copy was served"},"fetched_at":{"type":"string","format":"date-time"},"unit":{"type":"string"},"rate":{"type":"number","description":"Current key rate, % per annum"},"as_of":{"type":"string","format":"date"},"effective_since":{"type":["string","null"]},"previous_rate":{"type":["number","null"]},"last_change_bp":{"type":["integer","null"]},"months":{"type":"integer"},"max_in_window":{"type":"number"},"min_in_window":{"type":"number"},"changes":{"type":"array","description":"Rate changes in the window, newest first","items":{"type":"object","properties":{"date":{"type":"string","format":"date"},"rate":{"type":"number"},"prev_rate":{"type":"number"},"change_bp":{"type":"integer"}}}}}}}}},"400":{"description":"months is not a number. Returned before payment.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"402":{"description":"Payment Required. x402 v2 challenge in the PAYMENT-REQUIRED response header (base64 JSON).","headers":{"PAYMENT-REQUIRED":{"description":"Base64-encoded x402 PaymentRequired object","schema":{"type":"string"}}}},"502":{"description":"cbr.ru unreachable or returned an unexpected response. The x402 payment is not settled.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","enum":["upstream_unavailable"]},"detail":{"type":"string"}}}}}}}}},"/moex/quote":{"get":{"operationId":"getMoexQuote","summary":"Moscow Exchange stock quote (delayed ~15 min): price, change, volume, bid/offer","description":"One MOEX shares-market ticker from MOEX ISS (main board TQBR when listed): price (last trade, or previous close before the session's first trade), change/change_pct vs previous close, open/high/low, bid/offer, volume, value_rub, market cap, trading status. Data is delayed ~15 minutes (delayed: true). Unknown ticker -> 404 (not settled).","tags":["ru-data"],"security":[],"parameters":[{"name":"ticker","in":"query","required":true,"description":"MOEX ticker (SECID) on the shares market, e.g. SBER, GAZP, LKOH, YDEX, T","schema":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9._-]{0,11}$"}}],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.003"},"protocols":[{"x402":{"network":"eip155:8453","scheme":"exact","payTo":"0x2c257EE70952a16f00c99d40fDFF2d28f1A5b8A2","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","amount":"3000"}}]},"responses":{"200":{"description":"Quote","content":{"application/json":{"schema":{"type":"object","required":["ticker","board","price","price_source","delayed"],"properties":{"source":{"type":"string"},"via":{"type":"string","enum":["direct","proxy"]},"cached":{"type":"boolean"},"stale":{"type":"boolean","description":"true when the upstream failed and a recent cached copy was served"},"fetched_at":{"type":"string","format":"date-time"},"ticker":{"type":"string"},"board":{"type":"string"},"short_name":{"type":["string","null"]},"name":{"type":["string","null"]},"isin":{"type":["string","null"]},"currency":{"type":["string","null"]},"lot_size":{"type":["integer","null"]},"price":{"type":["number","null"],"description":"Last trade, or previous close before the first trade of the session"},"price_source":{"type":"string","enum":["last_trade","previous_close"]},"last":{"type":["number","null"]},"prev_close":{"type":["number","null"]},"prev_date":{"type":["string","null"]},"change":{"type":["number","null"]},"change_pct":{"type":["number","null"]},"open":{"type":["number","null"]},"high":{"type":["number","null"]},"low":{"type":["number","null"]},"bid":{"type":["number","null"]},"offer":{"type":["number","null"]},"waprice":{"type":["number","null"]},"volume":{"type":["number","null"]},"value_rub":{"type":["number","null"]},"num_trades":{"type":["integer","null"]},"market_cap_rub":{"type":["number","null"]},"trading_status":{"type":["string","null"]},"updated_at":{"type":["string","null"]},"trade_date":{"type":["string","null"]},"note":{"type":"string"},"delayed":{"type":"boolean","enum":[true]},"delay_minutes":{"type":"integer"},"note_delay":{"type":"string"}}}}}},"400":{"description":"ticker missing (with a payment attached) or not 1-12 letters/digits. Returned before payment.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"402":{"description":"Payment Required. x402 v2 challenge in the PAYMENT-REQUIRED response header (base64 JSON).","headers":{"PAYMENT-REQUIRED":{"description":"Base64-encoded x402 PaymentRequired object","schema":{"type":"string"}}}},"404":{"description":"Ticker not found on the MOEX shares market. The x402 payment is not settled.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","enum":["not_found"]},"detail":{"type":"string"}}}}}},"502":{"description":"iss.moex.com unreachable or returned an unexpected response. The x402 payment is not settled.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","enum":["upstream_unavailable"]},"detail":{"type":"string"}}}}}}}}},"/moex/index":{"get":{"operationId":"getMoexIndex","summary":"MOEX index values (IMOEX, RTSI, sector indices) or the index catalogue","description":"Index level, change/change_pct vs previous close, open/high/low, month/year change, annual high/low and traded value for up to 5 codes (default IMOEX), or code=list for the catalogue of MOEX stock indices (SNDX board + RTS*). Delayed ~15 minutes. Unknown codes -> 404 (not settled).","tags":["ru-data"],"security":[],"parameters":[{"name":"code","in":"query","required":false,"description":"Index code(s), up to 5 comma-separated (default IMOEX; e.g. RTSI, MOEXBMI, MOEXOG), or `list` for the catalogue of stock indices","schema":{"type":"string","pattern":"^([A-Za-z0-9]{2,16}(,[A-Za-z0-9]{2,16}){0,4}|list)$","default":"IMOEX"}}],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.003"},"protocols":[{"x402":{"network":"eip155:8453","scheme":"exact","payTo":"0x2c257EE70952a16f00c99d40fDFF2d28f1A5b8A2","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","amount":"3000"}}]},"responses":{"200":{"description":"Index values or catalogue","content":{"application/json":{"schema":{"type":"object","required":["mode","count","items"],"properties":{"source":{"type":"string"},"via":{"type":"string","enum":["direct","proxy"]},"cached":{"type":"boolean"},"stale":{"type":"boolean","description":"true when the upstream failed and a recent cached copy was served"},"fetched_at":{"type":"string","format":"date-time"},"mode":{"type":"string","enum":["quote","list"],"description":"list when code=list (items are {code, name})"},"count":{"type":"integer"},"items":{"type":"array","items":{"type":"object","required":["code"],"properties":{"code":{"type":"string"},"name":{"type":["string","null"]},"value":{"type":["number","null"]},"prev_close":{"type":["number","null"]},"change":{"type":["number","null"]},"change_pct":{"type":["number","null"]},"open":{"type":["number","null"]},"high":{"type":["number","null"]},"low":{"type":["number","null"]},"month_change_pct":{"type":["number","null"]},"year_change_pct":{"type":["number","null"]},"annual_high":{"type":["number","null"]},"annual_low":{"type":["number","null"]},"value_traded_rub":{"type":["number","null"]},"currency":{"type":["string","null"]},"trade_date":{"type":["string","null"]},"updated_at":{"type":["string","null"]}}}},"missing":{"type":"array","items":{"type":"string"}},"delayed":{"type":"boolean"},"delay_minutes":{"type":"integer"},"note_delay":{"type":"string"}}}}}},"400":{"description":"code is not up to 5 comma-separated index codes (2-16 letters/digits) or `list`. Returned before payment.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"402":{"description":"Payment Required. x402 v2 challenge in the PAYMENT-REQUIRED response header (base64 JSON).","headers":{"PAYMENT-REQUIRED":{"description":"Base64-encoded x402 PaymentRequired object","schema":{"type":"string"}}}},"404":{"description":"Index code not found. The x402 payment is not settled.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","enum":["not_found"]},"detail":{"type":"string"}}}}}},"502":{"description":"iss.moex.com unreachable or returned an unexpected response. The x402 payment is not settled.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","enum":["upstream_unavailable"]},"detail":{"type":"string"}}}}}}}}},"/moex/movers":{"get":{"operationId":"getMoexMovers","summary":"Top gainers and losers on the Moscow Exchange main board (TQBR), with market breadth","description":"Ranks TQBR shares by change vs previous close (turnover >= min_value RUB, default 5 mln): top `limit` gainers and losers (default 10, max 50), advancers/decliners/unchanged. Before the session's first trades (mode previous_session) it ranks the last completed session from ISS history. Delayed ~15 minutes.","tags":["ru-data"],"security":[],"parameters":[{"name":"limit","in":"query","required":false,"description":"Gainers and losers to return (each side, default 10, max 50)","schema":{"type":"integer","minimum":1,"maximum":50,"default":10}},{"name":"min_value","in":"query","required":false,"description":"Minimum turnover in RUB to count a stock (default 5000000; filters illiquid names)","schema":{"type":"string","pattern":"^[0-9]+([.,][0-9]+)?$","default":"5000000"}}],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.004"},"protocols":[{"x402":{"network":"eip155:8453","scheme":"exact","payTo":"0x2c257EE70952a16f00c99d40fDFF2d28f1A5b8A2","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","amount":"4000"}}]},"responses":{"200":{"description":"Movers","content":{"application/json":{"schema":{"type":"object","required":["mode","gainers","losers"],"properties":{"source":{"type":"string"},"via":{"type":"string","enum":["direct","proxy"]},"cached":{"type":"boolean"},"stale":{"type":"boolean","description":"true when the upstream failed and a recent cached copy was served"},"fetched_at":{"type":"string","format":"date-time"},"board":{"type":"string"},"mode":{"type":"string","enum":["live","previous_session"],"description":"previous_session before the first trades of the day"},"as_of":{"type":["string","null"]},"limit":{"type":"integer"},"min_value_rub":{"type":"number"},"universe":{"type":"integer"},"advancers":{"type":"integer"},"decliners":{"type":"integer"},"unchanged":{"type":"integer"},"gainers":{"type":"array","items":{"type":"object","required":["ticker","pct"],"properties":{"ticker":{"type":"string"},"name":{"type":["string","null"]},"price":{"type":["number","null"]},"pct":{"type":"number","description":"Change vs previous close, %"},"value":{"type":["number","null"],"description":"Turnover, RUB"},"prev_close":{"type":["number","null"]},"updated_at":{"type":["string","null"]},"trade_date":{"type":["string","null"]}}}},"losers":{"type":"array","items":{"type":"object","required":["ticker","pct"],"properties":{"ticker":{"type":"string"},"name":{"type":["string","null"]},"price":{"type":["number","null"]},"pct":{"type":"number","description":"Change vs previous close, %"},"value":{"type":["number","null"],"description":"Turnover, RUB"},"prev_close":{"type":["number","null"]},"updated_at":{"type":["string","null"]},"trade_date":{"type":["string","null"]}}}},"note":{"type":"string"},"delayed":{"type":"boolean"},"delay_minutes":{"type":"integer"},"note_delay":{"type":"string"}}}}}},"400":{"description":"limit or min_value is not a number. Returned before payment.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"402":{"description":"Payment Required. x402 v2 challenge in the PAYMENT-REQUIRED response header (base64 JSON).","headers":{"PAYMENT-REQUIRED":{"description":"Base64-encoded x402 PaymentRequired object","schema":{"type":"string"}}}},"502":{"description":"iss.moex.com unreachable or returned an unexpected response. The x402 payment is not settled.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","enum":["upstream_unavailable"]},"detail":{"type":"string"}}}}}}}}},"/ru/fuel":{"get":{"operationId":"getRuFuelPrices","summary":"Russian retail fuel prices (AI-92/95/98, diesel) — Rosstat weekly averages","description":"Average retail pump prices across Russia from Rosstat's weekly release (rosstat.gov.ru nedel_sred_cen.xlsx): price (RUB/l), as_of, week-over-week change, 4-week and year-to-date change and `weeks` of history per fuel. Rosstat publishes weekly (usually Wednesday, prices as of Monday); cached 6 h, a stale copy (stale: true) is served for up to 14 days if Rosstat is unreachable.","tags":["ru-data"],"security":[],"parameters":[{"name":"weeks","in":"query","required":false,"description":"Weekly history points to include per fuel (0-52, default 4)","schema":{"type":"integer","minimum":0,"maximum":52,"default":4}}],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.003"},"protocols":[{"x402":{"network":"eip155:8453","scheme":"exact","payTo":"0x2c257EE70952a16f00c99d40fDFF2d28f1A5b8A2","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","amount":"3000"}}]},"responses":{"200":{"description":"Fuel prices","content":{"application/json":{"schema":{"type":"object","required":["as_of","unit","prices","source_url"],"properties":{"source":{"type":"string"},"via":{"type":"string","enum":["direct","proxy"]},"cached":{"type":"boolean"},"stale":{"type":"boolean","description":"true when the upstream failed and a recent cached copy was served"},"fetched_at":{"type":"string","format":"date-time"},"source_url":{"type":"string","format":"uri"},"as_of":{"type":["string","null"]},"unit":{"type":"string"},"region":{"type":"string"},"prices":{"type":"array","items":{"type":"object","required":["fuel","price","as_of"],"properties":{"fuel":{"type":"string","enum":["ai92","ai95","ai98","diesel","petrol_avg"]},"name":{"type":"string"},"label_ru":{"type":["string","null"]},"price":{"type":"number","description":"RUB per litre"},"as_of":{"type":"string","format":"date"},"prev_price":{"type":["number","null"]},"prev_date":{"type":["string","null"]},"change":{"type":["number","null"]},"change_pct":{"type":["number","null"]},"change_4w_pct":{"type":["number","null"]},"change_ytd_pct":{"type":["number","null"]},"history":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string","format":"date"},"price":{"type":"number"}}}}}}},"note":{"type":"string"},"stale_reason":{"type":"string"}}}}}},"400":{"description":"weeks is not a number. Returned before payment.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"402":{"description":"Payment Required. x402 v2 challenge in the PAYMENT-REQUIRED response header (base64 JSON).","headers":{"PAYMENT-REQUIRED":{"description":"Base64-encoded x402 PaymentRequired object","schema":{"type":"string"}}}},"502":{"description":"rosstat.gov.ru unreachable or returned an unexpected response. The x402 payment is not settled.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","enum":["upstream_unavailable"]},"detail":{"type":"string"}}}}}}}}},"/tg/channel/latest":{"get":{"operationId":"getTelegramChannelLatest","summary":"Latest posts of a public Telegram channel (text, date, views, link)","description":"Reads the public web preview t.me/s/<channel> (no login): newest `limit` posts (default 20, max 50) with id, date, text (HTML stripped, emoji kept), views, link, media types and channel title/subscribers. Channels without a public preview or that do not exist -> 404 (not settled). Cached 2 min.","tags":["telegram"],"security":[],"parameters":[{"name":"channel","in":"query","required":true,"description":"Public Telegram channel username (5-32 chars; '@name' or a t.me link also accepted), e.g. markettwits","schema":{"type":"string","pattern":"^@?[A-Za-z][A-Za-z0-9_]{3,31}$"}},{"name":"limit","in":"query","required":false,"description":"Messages to return (default 20, max 50)","schema":{"type":"integer","minimum":1,"maximum":50,"default":20}}],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.004"},"protocols":[{"x402":{"network":"eip155:8453","scheme":"exact","payTo":"0x2c257EE70952a16f00c99d40fDFF2d28f1A5b8A2","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","amount":"4000"}}]},"responses":{"200":{"description":"Channel posts","content":{"application/json":{"schema":{"type":"object","required":["channel","count","items"],"properties":{"source":{"type":"string"},"via":{"type":"string","enum":["direct","proxy"]},"cached":{"type":"boolean"},"stale":{"type":"boolean","description":"true when the upstream failed and a recent cached copy was served"},"fetched_at":{"type":"string","format":"date-time"},"channel":{"type":"string"},"title":{"type":["string","null"]},"subscribers":{"type":["integer","null"]},"subscribers_raw":{"type":["string","null"]},"count":{"type":"integer"},"pages":{"type":"integer"},"items":{"type":"array","items":{"type":"object","required":["id","channel","date","text","link"],"properties":{"id":{"type":"integer"},"channel":{"type":"string"},"date":{"type":["string","null"],"format":"date-time"},"text":{"type":"string"},"views":{"type":["integer","null"]},"views_raw":{"type":["string","null"]},"link":{"type":"string","format":"uri"},"media":{"type":"array","items":{"type":"string","enum":["photo","video","document","poll"]}},"edited":{"type":"boolean"},"forwarded_from":{"type":"string"}}},"description":"Newest first"}}}}}},"400":{"description":"channel missing (with a payment attached) or not a valid username, or limit not a number. Returned before payment.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"402":{"description":"Payment Required. x402 v2 challenge in the PAYMENT-REQUIRED response header (base64 JSON).","headers":{"PAYMENT-REQUIRED":{"description":"Base64-encoded x402 PaymentRequired object","schema":{"type":"string"}}}},"404":{"description":"Channel not found or no public web preview. The x402 payment is not settled.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","enum":["not_found"]},"detail":{"type":"string"}}}}}},"502":{"description":"t.me unreachable or returned an unexpected response. The x402 payment is not settled.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","enum":["upstream_unavailable"]},"detail":{"type":"string"}}}}}}}}},"/tg/search":{"get":{"operationId":"searchTelegramChannels","summary":"Search up to 5 public Telegram channels for a keyword","description":"Runs Telegram's own channel search (t.me/s/<channel>?q=) on 1-5 public channels, merges the matches newest first (up to `limit`, default 20) with per-channel counts/errors. 404 when no channel exists, 502 when all fail; partial failures are reported in per_channel.","tags":["telegram"],"security":[],"parameters":[{"name":"q","in":"query","required":true,"description":"Keywords (case-insensitive). Several words = all must match. Hashtags match with or without '#', e.g. 'oil', '#Fed rates'.","schema":{"type":"string","minLength":1,"maxLength":100}},{"name":"channels","in":"query","required":true,"description":"1-5 comma-separated public channel usernames, e.g. markettwits,rbc_news","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Messages to return (default 20, max 50)","schema":{"type":"integer","minimum":1,"maximum":50,"default":20}}],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.006"},"protocols":[{"x402":{"network":"eip155:8453","scheme":"exact","payTo":"0x2c257EE70952a16f00c99d40fDFF2d28f1A5b8A2","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","amount":"6000"}}]},"responses":{"200":{"description":"Matches","content":{"application/json":{"schema":{"type":"object","required":["query","channels","count","items","per_channel"],"properties":{"source":{"type":"string"},"via":{"type":"string","enum":["direct","proxy"]},"cached":{"type":"boolean"},"stale":{"type":"boolean","description":"true when the upstream failed and a recent cached copy was served"},"fetched_at":{"type":"string","format":"date-time"},"query":{"type":"string"},"channels":{"type":"array","items":{"type":"string"}},"count":{"type":"integer"},"items":{"type":"array","items":{"type":"object","required":["id","channel","date","text","link"],"properties":{"id":{"type":"integer"},"channel":{"type":"string"},"date":{"type":["string","null"],"format":"date-time"},"text":{"type":"string"},"views":{"type":["integer","null"]},"views_raw":{"type":["string","null"]},"link":{"type":"string","format":"uri"},"media":{"type":"array","items":{"type":"string","enum":["photo","video","document","poll"]}},"edited":{"type":"boolean"},"forwarded_from":{"type":"string"}}},"description":"Merged, newest first"},"per_channel":{"type":"array","items":{"type":"object","properties":{"channel":{"type":"string"},"title":{"type":["string","null"]},"count":{"type":"integer"},"error":{"type":"string"},"detail":{"type":"string"}}}},"note":{"type":"string"}}}}}},"400":{"description":"q missing/empty/longer than 100 chars, channels missing/invalid/more than 5, or limit not a number (missing params with a payment attached). Returned before payment.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"402":{"description":"Payment Required. x402 v2 challenge in the PAYMENT-REQUIRED response header (base64 JSON).","headers":{"PAYMENT-REQUIRED":{"description":"Base64-encoded x402 PaymentRequired object","schema":{"type":"string"}}}},"404":{"description":"None of the channels exist / have a public preview. The x402 payment is not settled.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","enum":["not_found"]},"detail":{"type":"string"}}}}}},"502":{"description":"t.me unreachable or returned an unexpected response. The x402 payment is not settled.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","enum":["upstream_unavailable"]},"detail":{"type":"string"}}}}}}}}},"/product/info":{"get":{"operationId":"getProductInfo","summary":"Wildberries / Ozon product card: title, price (RUB), rating, reviews, stock","description":"Live product data for a Wildberries (wildberries.ru, wb.ru) or Ozon (ozon.ru) product URL: title, current price in RUB (original_amount = list price before discount when known), rating, reviews_count and availability. Cached 10 min per product. If the marketplace blocks or fails, returns 502 upstream_unavailable and the payment is NOT settled. Can take up to ~40s when the live page has to be rendered.","tags":["product"],"security":[],"parameters":[{"name":"url","in":"query","required":true,"description":"Product page URL: https://www.wildberries.ru/catalog/<id>/detail.aspx (also wb.ru, *.wildberries.ru) or https://www.ozon.ru/product/<slug>-<id>/ (also *.ozon.ru)","schema":{"type":"string","minLength":10,"maxLength":2000}}],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.004"},"protocols":[{"x402":{"network":"eip155:8453","scheme":"exact","payTo":"0x2c257EE70952a16f00c99d40fDFF2d28f1A5b8A2","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","amount":"4000"}}]},"responses":{"200":{"description":"Product data","content":{"application/json":{"schema":{"type":"object","required":["source","url","product_id","title","price","rating","reviews_count","availability","in_stock","fetched_at"],"properties":{"source":{"type":"string","enum":["wildberries","ozon"]},"url":{"type":"string","format":"uri","description":"Canonical product URL"},"product_id":{"type":"string","description":"Marketplace product id (WB nm id / Ozon SKU)"},"title":{"type":["string","null"]},"price":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"number","description":"Current price in RUB"},"currency":{"type":"string","enum":["RUB"]},"original_amount":{"type":"number","description":"List price before discount, when known"},"as_of":{"type":"string","description":"Only for the Wildberries static-CDN fallback: date of the weekly price point (YYYY-MM-DD)"}}},"rating":{"type":["number","null"],"description":"Average rating 0-5"},"reviews_count":{"type":["integer","null"]},"availability":{"type":"string","enum":["in_stock","out_of_stock","unknown"]},"in_stock":{"type":["boolean","null"]},"fetched_at":{"type":"string","format":"date-time"},"data_source":{"type":"string","description":"Which upstream answered (e.g. card.wb.ru v4, ozon page json-ld)"},"via":{"type":"string","enum":["browser","proxy","direct"],"description":"How the marketplace was reached: headless-browser parser, the server's proxy, or directly"},"cached":{"type":"boolean","description":"true when served from the 10-minute cache"}}}}}},"400":{"description":"url is not a valid http(s) URL, the host is not wildberries.ru/wb.ru/ozon.ru, or no product id could be extracted. Returned before payment.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"402":{"description":"Payment Required. x402 v2 challenge in the PAYMENT-REQUIRED response header (base64 JSON).","headers":{"PAYMENT-REQUIRED":{"description":"Base64-encoded x402 PaymentRequired object","schema":{"type":"string"}}}},"502":{"description":"Marketplace blocked or failed (anti-bot, timeout, product not found). The x402 payment is not settled.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","enum":["upstream_unavailable"]},"detail":{"type":"string"}}}}}}}}},"/product/compare":{"get":{"operationId":"compareProducts","summary":"Compare 2-5 Wildberries products: prices, cheapest, price spread, stock","description":"Fetches 2-5 product URLs (urls=comma-separated, or repeated url=) with the same live chain as /product/info and returns per-item title/price/original_price/in_stock/rating/reviews_count, the cheapest and most expensive item, price_diff (abs RUB and percent of the cheapest), in_stock_count and all_in_stock. Items that fail carry error/detail; returns 502 (payment not settled) only if fewer than 2 items returned a price.","tags":["product"],"security":[],"parameters":[{"name":"urls","in":"query","required":true,"description":"2-5 comma-separated product URLs (Wildberries; Ozon is accepted but currently blocked by its anti-bot). Alternatively repeat url= instead.","schema":{"type":"string","minLength":20,"maxLength":10000}}],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.006"},"protocols":[{"x402":{"network":"eip155:8453","scheme":"exact","payTo":"0x2c257EE70952a16f00c99d40fDFF2d28f1A5b8A2","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","amount":"6000"}}]},"responses":{"200":{"description":"Comparison (at least 2 items with a price; failed items have error)","content":{"application/json":{"schema":{"type":"object","required":["count","succeeded","items","cheapest","most_expensive","price_diff","in_stock_count","all_in_stock","fetched_at"],"properties":{"count":{"type":"integer"},"succeeded":{"type":"integer","description":"Items that returned a price (>= 2, else 502)"},"items":{"type":"array","items":{"type":"object","required":["product_id","url","title","price","in_stock"],"properties":{"product_id":{"type":"string"},"source":{"type":"string","enum":["wildberries","ozon"]},"url":{"type":"string","format":"uri"},"title":{"type":["string","null"]},"price":{"type":["number","null"],"description":"Current price, RUB (null when this item failed)"},"original_price":{"type":["number","null"],"description":"List price before discount, when known"},"in_stock":{"type":["boolean","null"]},"rating":{"type":["number","null"]},"reviews_count":{"type":["integer","null"]},"data_source":{"type":["string","null"]},"price_as_of":{"type":"string","description":"Only when the price came from the weekly CDN fallback"},"error":{"type":"string","enum":["upstream_unavailable","out_of_stock_no_price"],"description":"Present only on failed items"},"detail":{"type":"string"}}},"description":"In request order; failed items carry error/detail"},"cheapest":{"type":["object","null"],"properties":{"product_id":{"type":"string"},"url":{"type":"string"},"title":{"type":["string","null"]},"price":{"type":"number"}}},"most_expensive":{"type":["object","null"],"properties":{"product_id":{"type":"string"},"url":{"type":"string"},"title":{"type":["string","null"]},"price":{"type":"number"}}},"price_diff":{"type":["object","null"],"properties":{"abs":{"type":"number","description":"most_expensive - cheapest, RUB"},"percent":{"type":["number","null"],"description":"abs / cheapest * 100"}}},"in_stock_count":{"type":"integer"},"all_in_stock":{"type":"boolean","description":"true only if every requested item is in stock"},"currency":{"type":"string","enum":["RUB"]},"fetched_at":{"type":"string","format":"date-time"}}}}}},"400":{"description":"Fewer than 2 or more than 5 URLs, a duplicate product, or any URL that is invalid / not wildberries.ru, wb.ru or ozon.ru. Returned before payment.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"402":{"description":"Payment Required. x402 v2 challenge in the PAYMENT-REQUIRED response header (base64 JSON).","headers":{"PAYMENT-REQUIRED":{"description":"Base64-encoded x402 PaymentRequired object","schema":{"type":"string"}}}},"502":{"description":"Fewer than 2 products returned a price (anti-bot, timeout, not found). The x402 payment is not settled.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","enum":["upstream_unavailable"]},"detail":{"type":"string"}}}}}}}}},"/product/monitor":{"get":{"operationId":"monitorProductPrice","summary":"Price-target check for one product: is the current price at or below target_price?","description":"Fetches one Wildberries/Ozon product (same live chain as /product/info) and compares it with target_price (RUB): below_target (current <= target and not out of stock), current_price, diff_abs/diff_percent, in_stock, the full product object and checked_at. Use it as a paid poll for price alerts. If the product is out of stock with no price it returns 200 with below_target false, current_price null, in_stock false and a note; if no product data can be fetched at all it returns 502 and the payment is not settled.","tags":["product"],"security":[],"parameters":[{"name":"url","in":"query","required":true,"description":"Product page URL: https://www.wildberries.ru/catalog/<id>/detail.aspx (also wb.ru, *.wildberries.ru) or https://www.ozon.ru/product/<slug>-<id>/ (also *.ozon.ru)","schema":{"type":"string","minLength":10,"maxLength":2000}},{"name":"target_price","in":"query","required":true,"description":"Target price in RUB, a positive number (e.g. 1500 or 1499.90)","schema":{"type":"string","pattern":"^[0-9]+([.,][0-9]+)?$"}}],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.005"},"protocols":[{"x402":{"network":"eip155:8453","scheme":"exact","payTo":"0x2c257EE70952a16f00c99d40fDFF2d28f1A5b8A2","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","amount":"5000"}}]},"responses":{"200":{"description":"Target check result","content":{"application/json":{"schema":{"type":"object","required":["below_target","current_price","target_price","diff_abs","diff_percent","in_stock","checked_at","product_id","url"],"properties":{"url":{"type":"string","format":"uri"},"product_id":{"type":"string"},"title":{"type":["string","null"]},"below_target":{"type":"boolean","description":"current_price <= target_price and the product is not out of stock (false when there is no current price)"},"current_price":{"type":["number","null"],"description":"RUB; null only when the product is out of stock with no price"},"original_price":{"type":["number","null"]},"target_price":{"type":"number"},"currency":{"type":"string","enum":["RUB"]},"diff_abs":{"type":["number","null"],"description":"current_price - target_price (negative = below target)"},"diff_percent":{"type":["number","null"],"description":"diff_abs / target_price * 100"},"in_stock":{"type":["boolean","null"]},"note":{"type":"string"},"product":{"type":"object","description":"Full /product/info-style product object"},"checked_at":{"type":"string","format":"date-time"}}}}}},"400":{"description":"url invalid/unsupported, or target_price missing, non-numeric, zero or negative. Returned before payment.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"402":{"description":"Payment Required. x402 v2 challenge in the PAYMENT-REQUIRED response header (base64 JSON).","headers":{"PAYMENT-REQUIRED":{"description":"Base64-encoded x402 PaymentRequired object","schema":{"type":"string"}}}},"502":{"description":"No product data could be fetched (anti-bot, timeout, not found). The x402 payment is not settled.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","enum":["upstream_unavailable"]},"detail":{"type":"string"}}}}}}}}},"/product/history":{"get":{"operationId":"getProductPriceHistory","summary":"Wildberries price history: weekly CDN points + observed + live price, min/max/avg, 30-day change","description":"Price history for a Wildberries product: weekly points from WB's public price-history CDN (weekly_cdn), prices this service observed on earlier lookups (observed; in-memory, reset on restart), and the current live price (live). Returns points (oldest first), current, stats min/max/avg, change_30d (vs. the latest point at least 30 days old) and history_limited:true with a note when only the current price exists. Ozon has no public history (only live, currently blocked). 502 (not settled) only when no price at all is available.","tags":["product"],"security":[],"parameters":[{"name":"url","in":"query","required":true,"description":"Product page URL: https://www.wildberries.ru/catalog/<id>/detail.aspx (also wb.ru, *.wildberries.ru) or https://www.ozon.ru/product/<slug>-<id>/ (also *.ozon.ru)","schema":{"type":"string","minLength":10,"maxLength":2000}}],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.004"},"protocols":[{"x402":{"network":"eip155:8453","scheme":"exact","payTo":"0x2c257EE70952a16f00c99d40fDFF2d28f1A5b8A2","asset":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913","amount":"4000"}}]},"responses":{"200":{"description":"Price history","content":{"application/json":{"schema":{"type":"object","required":["product_id","url","current","points","stats","change_30d","history_limited","checked_at"],"properties":{"url":{"type":"string","format":"uri"},"product_id":{"type":"string"},"source":{"type":"string"},"title":{"type":["string","null"]},"currency":{"type":"string","enum":["RUB"]},"current":{"type":"object","properties":{"price":{"type":"number"},"original_price":{"type":["number","null"]},"source":{"type":"string","enum":["live","weekly_cdn","observed"]},"date":{"type":"string"}}},"points":{"type":"array","description":"Oldest first","items":{"type":"object","required":["date","price","source"],"properties":{"date":{"type":"string","description":"YYYY-MM-DD for weekly_cdn points, ISO date-time for observed/live"},"price":{"type":"number"},"source":{"type":"string","enum":["weekly_cdn","observed","live"]}}}},"stats":{"type":"object","properties":{"min":{"type":"number"},"max":{"type":"number"},"avg":{"type":"number"},"count":{"type":"integer"},"from":{"type":"string"},"to":{"type":"string"}}},"change_30d":{"type":["object","null"],"description":"current vs. the latest point at least 30 days old (null if none)","properties":{"vs_date":{"type":"string"},"vs_price":{"type":"number"},"abs":{"type":"number"},"percent":{"type":"number"}}},"history_limited":{"type":"boolean","description":"true when only the current price is available"},"note":{"type":"string"},"sources":{"type":"object","properties":{"weekly_cdn":{"type":"integer"},"observed":{"type":"integer"},"live":{"type":"integer"}}},"checked_at":{"type":"string","format":"date-time"}}}}}},"400":{"description":"url is not a valid http(s) URL, the host is not wildberries.ru/wb.ru/ozon.ru, or no product id could be extracted. Returned before payment.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"402":{"description":"Payment Required. x402 v2 challenge in the PAYMENT-REQUIRED response header (base64 JSON).","headers":{"PAYMENT-REQUIRED":{"description":"Base64-encoded x402 PaymentRequired object","schema":{"type":"string"}}}},"502":{"description":"No price at all (no weekly history and the live fetch failed). The x402 payment is not settled.","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","enum":["upstream_unavailable"]},"detail":{"type":"string"}}}}}}}}},"/news/sample":{"get":{"operationId":"getNewsSample","summary":"Free sample: newest item with truncated text","tags":["news"],"security":[],"responses":{"200":{"description":"Sample item","content":{"application/json":{"schema":{"type":"object","properties":{"description":{"type":"string"},"item":{"oneOf":[{"$ref":"#/components/schemas/NewsItem"},{"type":"null"}]}}}}}}}}},"/health":{"get":{"operationId":"getHealth","summary":"Service status (free)","tags":["meta"],"security":[],"responses":{"200":{"description":"Status","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"mode":{"type":"string"},"network":{"type":"string"},"facilitator":{"type":"string"},"price":{"type":"string"},"items":{"type":"integer"},"newest_id":{"type":["integer","null"]},"proxy_configured":{"type":"boolean","description":"Whether a marketplace proxy is configured (no details exposed)"}}}}}}}}}},"components":{"schemas":{"NewsItem":{"type":"object","required":["id","source_url","published_at","importance","text_en"],"properties":{"id":{"type":"integer","description":"Telegram post id in t.me/markettwits","examples":[389638]},"source_url":{"type":"string","format":"uri","description":"Original Russian post"},"published_at":{"type":"string","format":"date-time","description":"Publication time of the original post (ISO 8601)"},"importance":{"type":"string","enum":["high","medium","low"]},"text_en":{"type":"string","description":"English translation of the post"},"posted_to_x":{"type":"boolean","description":"Whether the item was also posted to X"},"buffer_post_id":{"type":["string","null"],"description":"Buffer post id when posted to X, else null"}}}}}}