| <!DOCTYPE html> |
| <html lang="en" dir="ltr" data-theme="light"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <meta name="description" content="Complete API Help Guide for Crypto Monitor on Hugging Face Spaces"> |
| <title>Help & API Guide | Crypto Monitor</title> |
| <link rel="icon" type="image/svg+xml" href="/static/assets/icons/favicon.svg"> |
| <link rel="stylesheet" href="/static/shared/css/design-system.css"> |
| <link rel="stylesheet" href="/static/shared/css/global.css"> |
| <link rel="stylesheet" href="/static/shared/css/components.css"> |
| <link rel="stylesheet" href="/static/shared/css/layout.css"> |
| <link rel="stylesheet" href="/static/pages/help/help.css?v=5.0"> |
| <script src="/static/js/api-config.js"></script> |
| </head> |
| <body> |
| <div class="app-container"> |
| <aside id="sidebar-container"></aside> |
| <main class="main-content"> |
| <header id="header-container"></header> |
| <div class="page-content"> |
| <div class="page-header"> |
| <div class="page-title"> |
| <h1>Help & API Guide</h1> |
| <p class="page-subtitle"> |
| Complete English reference for <strong>Datasourceforcryptocurrency-2</strong> (primary Space) and |
| <strong>v4 complement</strong>. Copy any example and run it β no setup beyond this URL. |
| </p> |
| <p class="page-subtitle"> |
| <strong>API Base:</strong> <code id="api-base-display"></code> |
| | <a href="/docs" target="_blank">Swagger UI</a> |
| | <a href="/api-explorer">API Explorer</a> |
| | <a href="/help/legacy">Extended legacy guide</a> |
| | <a href="/api/pages/catalog">Pages catalog API</a> |
| </p> |
| </div> |
| </div> |
|
|
| <div class="help-search-wrap"> |
| <input type="search" id="help-search" placeholder="Search help (e.g. sentiment, models, rotation)..." aria-label="Search help"> |
| </div> |
|
|
| <div id="live-stats" class="live-stats" aria-live="polite">Loading live system stats...</div> |
|
|
| <div class="help-layout"> |
| <nav class="help-toc" aria-label="Table of contents"> |
| <h3>Contents</h3> |
| <ul> |
| <li><a href="#quick-start">Quick Start</a></li> |
| <li><a href="#discovery">Discovery</a></li> |
| <li><a href="#dashboard">Dashboard API</a></li> |
| <li><a href="#market">Market Data</a></li> |
| <li><a href="#sentiment">Sentiment</a></li> |
| <li><a href="#models">AI Models</a></li> |
| <li><a href="#rotation">Rotation & Keys</a></li> |
| <li><a href="#news">News</a></li> |
| <li><a href="#indicators">Indicators</a></li> |
| <li><a href="#v4">v4 Complement</a></li> |
| <li><a href="#errors">Errors</a></li> |
| </ul> |
| </nav> |
|
|
| <div class="help-main"> |
|
|
| <section class="help-section" id="quick-start"> |
| <h2>1. Quick Start (3 steps)</h2> |
| <p>Every example uses your current origin. Replace <code>BASE</code> if you call from another app.</p> |
| <div class="code-wrap"> |
| <button class="copy-btn" type="button" data-copy="">Copy</button> |
| <pre class="code-block"><code>const BASE = window.location.origin; // e.g. https://really-amin-datasourceforcryptocurrency-2.hf.space |
|
|
| // Step 1 β Is the server alive? |
| const health = await fetch(`${BASE}/health`).then(r => r.json()); |
| console.log(health.status); // "healthy" |
|
|
| // Step 2 β Dashboard numbers (cards on home page) |
| const dash = await fetch(`${BASE}/api/dashboard/overview`).then(r => r.json()); |
| console.log(dash.cards); |
|
|
| // Step 3 β Analyze one sentence |
| const sentiment = await fetch(`${BASE}/api/sentiment`, { |
| method: 'POST', |
| headers: { 'Content-Type': 'application/json' }, |
| body: JSON.stringify({ text: 'Bitcoin looks bullish today' }) |
| }).then(r => r.json()); |
| console.log(sentiment.sentiment, sentiment.confidence);</code></pre> |
| </div> |
| <p class="help-note"><strong>Python:</strong> use <code>requests.get(BASE + "/health")</code> the same way. Always set <code>timeout=30</code> on HF Spaces.</p> |
| </section> |
|
|
| <section class="help-section" id="discovery"> |
| <h2>2. Discovery & Health</h2> |
| <p>Find every endpoint before you integrate.</p> |
| <table class="api-table"> |
| <thead><tr><th>Method</th><th>Path</th><th>What you get</th></tr></thead> |
| <tbody> |
| <tr><td class="method-get">GET</td><td><code>/health</code></td><td>Simple alive check (also <code>/api/health</code>)</td></tr> |
| <tr><td class="method-get">GET</td><td><code>/api/status</code></td><td>Provider connectivity probe</td></tr> |
| <tr><td class="method-get">GET</td><td><code>/api/system/status</code></td><td>Full system drawer data (pools, models, keys)</td></tr> |
| <tr><td class="method-get">GET</td><td><code>/api/endpoints</code></td><td>Grouped list of all routes</td></tr> |
| <tr><td class="method-get">GET</td><td><code>/api/routers</code></td><td>Which routers are loaded</td></tr> |
| <tr><td class="method-get">GET</td><td><code>/api/uptime/probe</code></td><td>Probe 12 critical endpoints</td></tr> |
| <tr><td class="method-get">GET</td><td><code>/docs</code></td><td>Interactive Swagger UI</td></tr> |
| </tbody> |
| </table> |
| <div class="code-wrap"> |
| <button class="copy-btn" type="button">Copy</button> |
| <pre class="code-block"><code>curl "%BASE%/api/endpoints" |
| curl "%BASE%/api/routers"</code></pre> |
| </div> |
| </section> |
|
|
| <section class="help-section" id="dashboard"> |
| <h2>3. Dashboard API</h2> |
| <p>The home dashboard reads one endpoint for all hero cards.</p> |
| <table class="api-table"> |
| <thead><tr><th>Method</th><th>Path</th><th>Response highlights</th></tr></thead> |
| <tbody> |
| <tr><td class="method-get">GET</td><td><code>/api/dashboard/overview</code></td><td><code>cards</code>: resources, API keys, models v2+v4, rotation pools</td></tr> |
| <tr><td class="method-get">GET</td><td><code>/api/resources/summary</code></td><td>Registry totals and categories</td></tr> |
| <tr><td class="method-get">GET</td><td><code>/api/models/summary</code></td><td>Models by category + v4 complement block</td></tr> |
| </tbody> |
| </table> |
| <div class="code-wrap"> |
| <button class="copy-btn" type="button">Copy</button> |
| <pre class="code-block"><code>const overview = await fetch(`${BASE}/api/dashboard/overview`).then(r => r.json()); |
| // cards.total_resources, cards.api_keys_env, cards.api_keys_file |
| // cards.models_loaded_v2, cards.models_loaded_v4, cards.pools_healthy</code></pre> |
| </div> |
| </section> |
|
|
| <section class="help-section" id="market"> |
| <h2>4. Market Data</h2> |
| <p>Prices, top coins, OHLCV. Automatic fallback: local β Binance β v4 complement β cache.</p> |
| <table class="api-table"> |
| <thead><tr><th>Method</th><th>Path</th><th>Parameters</th></tr></thead> |
| <tbody> |
| <tr><td class="method-get">GET</td><td><code>/api/market?limit=50</code></td><td>Top market rows for dashboard table</td></tr> |
| <tr><td class="method-get">GET</td><td><code>/api/coins/top?limit=50</code></td><td>Top coins by market cap</td></tr> |
| <tr><td class="method-get">GET</td><td><code>/api/trending</code></td><td>Trending coins</td></tr> |
| <tr><td class="method-get">GET</td><td><code>/api/ohlcv?symbol=BTC&timeframe=1h&limit=100</code></td><td>Candles for charts</td></tr> |
| <tr><td class="method-get">GET</td><td><code>/api/klines?symbol=BTCUSDT&interval=1h&limit=100</code></td><td>Binance-style alias</td></tr> |
| <tr><td class="method-get">GET</td><td><code>/api/market/gainers?limit=20</code></td><td>Top gainers (with fallbacks)</td></tr> |
| <tr><td class="method-get">GET</td><td><code>/api/market/losers?limit=20</code></td><td>Top losers</td></tr> |
| </tbody> |
| </table> |
| <div class="code-wrap"> |
| <button class="copy-btn" type="button">Copy</button> |
| <pre class="code-block"><code>// Market table data |
| const market = await fetch(`${BASE}/api/market?limit=20`).then(r => r.json()); |
|
|
| // OHLCV for TradingView-style charts |
| const ohlcv = await fetch(`${BASE}/api/ohlcv?symbol=BTC&timeframe=1h&limit=200`).then(r => r.json());</code></pre> |
| </div> |
| </section> |
|
|
| <section class="help-section" id="sentiment"> |
| <h2>5. Sentiment & Fear/Greed</h2> |
| <table class="api-table"> |
| <thead><tr><th>Method</th><th>Path</th><th>Body / notes</th></tr></thead> |
| <tbody> |
| <tr><td class="method-get">GET</td><td><code>/api/fear-greed?limit=30</code></td><td>Fear & Greed index + history</td></tr> |
| <tr><td class="method-get">GET</td><td><code>/api/sentiment/global</code></td><td>Global market mood</td></tr> |
| <tr><td class="method-get">GET</td><td><code>/api/sentiment/asset/BTC</code></td><td>Per-asset sentiment</td></tr> |
| <tr><td class="method-post">POST</td><td><code>/api/sentiment</code></td><td><code>{"text":"..."}</code> β v2 then v4 fallback</td></tr> |
| <tr><td class="method-post">POST</td><td><code>/api/sentiment/analyze</code></td><td><code>{"text":"...","mode":"crypto"}</code></td></tr> |
| <tr><td class="method-post">POST</td><td><code>/api/hf/run-sentiment</code></td><td><code>{"texts":["sentence 1"]}</code> β must be array</td></tr> |
| </tbody> |
| </table> |
| <div class="code-wrap"> |
| <button class="copy-btn" type="button">Copy</button> |
| <pre class="code-block"><code>// Fear & Greed (dashboard chart) |
| const fng = await fetch(`${BASE}/api/fear-greed?limit=30`).then(r => r.json()); |
|
|
| // Text sentiment |
| const result = await fetch(`${BASE}/api/sentiment`, { |
| method: 'POST', |
| headers: { 'Content-Type': 'application/json' }, |
| body: JSON.stringify({ text: 'ETH breaking resistance, very bullish' }) |
| }).then(r => r.json());</code></pre> |
| </div> |
| </section> |
|
|
| <section class="help-section" id="models"> |
| <h2>6. AI Models (Hugging Face)</h2> |
| <p><strong>v2</strong> loads models locally when possible. <strong>v4 complement</strong> adds more models via Inference API when v2 is exhausted.</p> |
| <table class="api-table"> |
| <thead><tr><th>Method</th><th>Path</th><th>Purpose</th></tr></thead> |
| <tbody> |
| <tr><td class="method-get">GET</td><td><code>/api/models/summary</code></td><td>Best for UI β categories + v4 block</td></tr> |
| <tr><td class="method-get">GET</td><td><code>/api/models/status</code></td><td>Registry status, <code>models_loaded</code></td></tr> |
| <tr><td class="method-get">GET</td><td><code>/api/models/list</code></td><td>Full catalog</td></tr> |
| <tr><td class="method-get">GET</td><td><code>/api/models/health</code></td><td>Per-model health entries</td></tr> |
| <tr><td class="method-get">GET</td><td><code>/api/hf/models</code></td><td>Alias β models list</td></tr> |
| <tr><td class="method-get">GET</td><td><code>/api/hf/health</code></td><td>HF connectivity check</td></tr> |
| <tr><td class="method-post">POST</td><td><code>/api/models/reinitialize</code></td><td>Warm models again</td></tr> |
| <tr><td class="method-post">POST</td><td><code>/api/ai/decision</code></td><td><code>{"symbol":"BTC","horizon":"swing"}</code></td></tr> |
| </tbody> |
| </table> |
| <div class="code-wrap"> |
| <button class="copy-btn" type="button">Copy</button> |
| <pre class="code-block"><code>const summary = await fetch(`${BASE}/api/models/summary`).then(r => r.json()); |
| console.log('v2 loaded:', summary.summary?.loaded_models); |
| console.log('v4 loaded:', summary.complement_v4?.loaded); |
|
|
| // HF sentiment batch (texts must be an array) |
| await fetch(`${BASE}/api/hf/run-sentiment`, { |
| method: 'POST', |
| headers: { 'Content-Type': 'application/json' }, |
| body: JSON.stringify({ texts: ['BTC pump incoming'] }) |
| });</code></pre> |
| </div> |
| <p class="help-note">Set Space secret <code>HF_TOKEN</code> and variable <code>HF_MODE=auth</code> for gated models. v4 Space uses Inference API when local torch is unavailable.</p> |
| </section> |
|
|
| <section class="help-section" id="rotation"> |
| <h2>7. API Keys, Resources & Rotation</h2> |
| <p>Keys come from <strong>HF Secrets</strong> (env) plus <strong>inline keys</strong> in <code>config/api_keys.json</code>. Rotation uses <code>api-resources/crypto_resources_unified_2025-11-11.json</code> (10 pools).</p> |
| <h3>Recommended Space secrets</h3> |
| <ul class="help-list"> |
| <li><code>CRYPTOCOMPARE_API_KEY</code>, <code>COINMARKETCAP_KEY_1</code>, <code>COINMARKETCAP_KEY_2</code></li> |
| <li><code>ETHERSCAN_KEY_1</code>, <code>ETHERSCAN_KEY_2</code>, <code>BSCSCAN_API_KEY</code>, <code>TRONSCAN_API_KEY</code></li> |
| <li><code>NEWSAPI_KEY</code>, <code>HF_TOKEN</code>, <code>COINGECKO_API_KEY</code> (optional)</li> |
| </ul> |
| <table class="api-table"> |
| <thead><tr><th>Method</th><th>Path</th><th>Purpose</th></tr></thead> |
| <tbody> |
| <tr><td class="method-get">GET</td><td><code>/api/resources/rotation/health</code></td><td>10 pools + env key probe</td></tr> |
| <tr><td class="method-get">GET</td><td><code>/api/resources/rotation</code></td><td>Full rotation status</td></tr> |
| <tr><td class="method-get">GET</td><td><code>/api/resources/fallback-chains</code></td><td>Failover chain JSON</td></tr> |
| <tr><td class="method-get">GET</td><td><code>/api/resources/summary</code></td><td>Registry + key counts</td></tr> |
| <tr><td class="method-get">GET</td><td><code>/api/providers</code></td><td>Named provider list</td></tr> |
| <tr><td class="method-get">GET</td><td><code>/api/complement/v4/status</code></td><td>v4 Space health</td></tr> |
| </tbody> |
| </table> |
| <div class="code-wrap"> |
| <button class="copy-btn" type="button">Copy</button> |
| <pre class="code-block"><code>const rotation = await fetch(`${BASE}/api/resources/rotation/health`).then(r => r.json()); |
| console.log(rotation.pools_healthy, '/', rotation.pools_total); |
| console.log('Env keys:', rotation.env_keys?.configured);</code></pre> |
| </div> |
| </section> |
|
|
| <section class="help-section" id="news"> |
| <h2>8. News</h2> |
| <table class="api-table"> |
| <thead><tr><th>Method</th><th>Path</th><th>Notes</th></tr></thead> |
| <tbody> |
| <tr><td class="method-get">GET</td><td><code>/api/news/latest?limit=20</code></td><td>Latest crypto news</td></tr> |
| <tr><td class="method-get">GET</td><td><code>/api/news?limit=20</code></td><td>Alias</td></tr> |
| </tbody> |
| </table> |
| <div class="code-wrap"> |
| <button class="copy-btn" type="button">Copy</button> |
| <pre class="code-block"><code>const news = await fetch(`${BASE}/api/news/latest?limit=10`).then(r => r.json()); |
| (news.articles || news.news || []).forEach(a => console.log(a.title));</code></pre> |
| </div> |
| </section> |
|
|
| <section class="help-section" id="indicators"> |
| <h2>9. Indicators & Technical Analysis</h2> |
| <table class="api-table"> |
| <thead><tr><th>Method</th><th>Path</th><th>Notes</th></tr></thead> |
| <tbody> |
| <tr><td class="method-get">GET</td><td><code>/api/indicators/services</code></td><td>List indicator services</td></tr> |
| <tr><td class="method-get">GET</td><td><code>/api/indicators/rsi?symbol=BTC&timeframe=1h</code></td><td>RSI</td></tr> |
| <tr><td class="method-get">GET</td><td><code>/api/indicators/macd?symbol=BTC&timeframe=1h</code></td><td>MACD</td></tr> |
| <tr><td class="method-get">GET</td><td><code>/api/indicators/comprehensive?symbol=BTC</code></td><td>Multi-indicator bundle</td></tr> |
| <tr><td class="method-post">POST</td><td><code>/api/technical/ta-quick</code></td><td>Body: symbol, timeframe, ohlcv array</td></tr> |
| <tr><td class="method-post">POST</td><td><code>/api/technical/comprehensive</code></td><td>Combined TA + FA + on-chain</td></tr> |
| </tbody> |
| </table> |
| <div class="code-wrap"> |
| <button class="copy-btn" type="button">Copy</button> |
| <pre class="code-block"><code>const ohlcv = await fetch(`${BASE}/api/ohlcv?symbol=BTC&timeframe=4h&limit=200`).then(r => r.json()); |
| const ta = await fetch(`${BASE}/api/technical/ta-quick`, { |
| method: 'POST', |
| headers: { 'Content-Type': 'application/json' }, |
| body: JSON.stringify({ symbol: 'BTC', timeframe: '4h', ohlcv: ohlcv.data }) |
| }).then(r => r.json());</code></pre> |
| </div> |
| </section> |
|
|
| <section class="help-section" id="v4"> |
| <h2>10. v4 Complement Space</h2> |
| <p>Secondary Space: <code>https://really-amin-datasourceforcryptocurrency-4.hf.space</code>. v2 calls it when local providers or models are exhausted.</p> |
| <ul class="help-list"> |
| <li>v2 <code>POST /api/sentiment</code> β local model β v4 β lexical fallback</li> |
| <li>v2 <code>/api/models/summary</code> includes <code>complement_v4</code> counts</li> |
| <li>v4 runs HF Inference API with <code>HF_MODE=auth</code> when torch is unavailable</li> |
| </ul> |
| <div class="code-wrap"> |
| <button class="copy-btn" type="button">Copy</button> |
| <pre class="code-block"><code>const v4 = await fetch(`${BASE}/api/complement/v4/status`).then(r => r.json()); |
| console.log(v4.probe); // endpoints_ok, healthy</code></pre> |
| </div> |
| </section> |
|
|
| <section class="help-section" id="errors"> |
| <h2>11. Errors & Tips</h2> |
| <ol class="help-steps"> |
| <li><strong>404 on route</strong> β Check <code>/api/endpoints</code> or <code>/docs</code>; path may differ from old docs.</li> |
| <li><strong>503 on market</strong> β CoinGecko rate limit; retry or use <code>/api/market</code> (Binance fallback).</li> |
| <li><strong>422 on sentiment</strong> β <code>/api/hf/run-sentiment</code> requires <code>{"texts":["..."]}</code> (array), not a single string.</li> |
| <li><strong>Empty models</strong> β Call <code>POST /api/models/reinitialize</code> or wait for lazy load; check <code>HF_TOKEN</code>.</li> |
| <li><strong>Space sleeping</strong> β First request may take 30β60s; increase client timeout.</li> |
| <li><strong>Hard refresh UI</strong> β <code>Ctrl+Shift+R</code> after deploys.</li> |
| </ol> |
| <h3>Diagnostic checklist</h3> |
| <div class="code-wrap"> |
| <button class="copy-btn" type="button">Copy</button> |
| <pre class="code-block"><code>curl "%BASE%/health" |
| curl "%BASE%/api/dashboard/overview" |
| curl "%BASE%/api/resources/rotation/health" |
| curl "%BASE%/api/models/summary"</code></pre> |
| </div> |
| <p class="help-note"> |
| <strong>HTTP only required.</strong> WebSocket endpoints are optional; the dashboard polls REST every 30 seconds. |
| For interactive testing, open <a href="/docs">/docs</a> or click the green <strong>?</strong> floating button on the dashboard. |
| </p> |
| </section> |
|
|
| </div> |
| </div> |
| </div> |
| </main> |
| </div> |
|
|
| <script type="module"> |
| import { LayoutManager } from '/static/shared/js/core/layout-manager.js'; |
| import HelpPage from '/static/pages/help/help.js?v=5.0'; |
| |
| document.getElementById('api-base-display').textContent = window.location.origin; |
| |
| document.querySelectorAll('.code-wrap').forEach(wrap => { |
| const code = wrap.querySelector('code'); |
| const btn = wrap.querySelector('.copy-btn'); |
| if (code && btn) { |
| btn.setAttribute('data-copy', code.textContent.replace(/%BASE%/g, window.location.origin)); |
| code.textContent = code.textContent.replace(/%BASE%/g, window.location.origin); |
| } |
| }); |
| |
| document.addEventListener('DOMContentLoaded', async () => { |
| await LayoutManager.init('help'); |
| const page = new HelpPage(); |
| await page.init(); |
| }); |
| </script> |
| </body> |
| </html> |
|
|