Really-amin's picture
Upload backend/services/api_help_guide.py with huggingface_hub
3216cd7 verified
Raw
History Blame Contribute Delete
27.3 kB
#!/usr/bin/env python3
"""
Machine-readable API help guide for humans, LLMs, and simple AI agents.
Served at GET /api/max/help and mirrored to api-resources/ai_api_help_guide.json.
Write every section in plain English with explicit intent → endpoint mapping.
"""
from __future__ import annotations
import json
from datetime import datetime, timezone
from pathlib import Path
from typing import Any, Dict, List
ROOT = Path(__file__).resolve().parents[2]
GUIDE_JSON_PATH = ROOT / "api-resources" / "ai_api_help_guide.json"
DEFAULT_BASE = "https://really-amin-datasourceforcryptocurrency-1.hf.space"
def _now_iso() -> str:
return datetime.now(timezone.utc).isoformat()
# ---------------------------------------------------------------------------
# Intent map — dumb-AI friendly: match keywords → call this endpoint
# ---------------------------------------------------------------------------
INTENT_MAP: List[Dict[str, Any]] = [
{
"id": "health_check",
"user_wants": "Check if the API server is alive",
"keywords": ["health", "alive", "ping", "status", "up"],
"method": "GET",
"path": "/api/max/health",
"query_params": {},
"path_params": {},
"returns": "success, status, resource_registry, cache",
"example_url": "{BASE}/api/max/health",
},
{
"id": "list_all_endpoints",
"user_wants": "List every API endpoint grouped by category",
"keywords": ["catalog", "endpoints", "list apis", "discovery", "openapi"],
"method": "GET",
"path": "/api/max/endpoints/catalog",
"query_params": {},
"path_params": {},
"returns": "groups, endpoints[], swagger link",
"example_url": "{BASE}/api/max/endpoints/catalog",
},
{
"id": "full_help_json",
"user_wants": "Download the complete machine-readable help document",
"keywords": ["help", "documentation", "guide", "ai agent", "llm"],
"method": "GET",
"path": "/api/max/help",
"query_params": {},
"path_params": {},
"returns": "This entire document as JSON",
"example_url": "{BASE}/api/max/help",
},
{
"id": "app_startup_bundle",
"user_wants": "One call to bootstrap a trading app at startup",
"keywords": ["bootstrap", "startup", "init", "main app", "short hunter"],
"method": "GET",
"path": "/api/max/app/bootstrap",
"query_params": {"symbols": "BTC,ETH,SOL"},
"path_params": {},
"returns": "providers, market snapshot, sentiment, fallback plan, capabilities",
"example_url": "{BASE}/api/max/app/bootstrap?symbols=BTC,ETH,SOL",
},
{
"id": "one_symbol_everything",
"user_wants": "Get ALL data for one coin in a single request (best for main apps)",
"keywords": ["symbol bundle", "btc data", "everything for eth", "combined", "one symbol"],
"method": "GET",
"path": "/api/max/app/symbol/{symbol}",
"query_params": {},
"path_params": {"symbol": "BTC"},
"returns": "price, ohlcv, orderbook, futures_market, futures_validation, sentiment, news, indicators",
"example_url": "{BASE}/api/max/app/symbol/BTC",
},
{
"id": "multi_symbol_scanner",
"user_wants": "Feed multiple symbols for a scanner or watchlist",
"keywords": ["universe", "scanner", "multiple symbols", "watchlist feed"],
"method": "GET",
"path": "/api/max/app/universe",
"query_params": {"symbols": "BTC,ETH,SOL"},
"path_params": {},
"returns": "items[] per symbol with price and analysis helper",
"example_url": "{BASE}/api/max/app/universe?symbols=BTC,ETH,SOL",
},
{
"id": "spot_price",
"user_wants": "Get current spot price for a cryptocurrency",
"keywords": ["price", "spot", "btc price", "eth price", "ticker"],
"method": "GET",
"path": "/api/max/market/price/{symbol}",
"query_params": {},
"path_params": {"symbol": "BTC"},
"returns": "price, source, data_state REAL|UNAVAILABLE, fallback attempts",
"example_url": "{BASE}/api/max/market/price/BTC",
},
{
"id": "spot_prices_multi",
"user_wants": "Get prices for several coins at once",
"keywords": ["snapshot", "multiple prices", "market snapshot"],
"method": "GET",
"path": "/api/max/market/snapshot",
"query_params": {"symbols": "BTC,ETH,SOL"},
"path_params": {},
"returns": "items[] with price per symbol",
"example_url": "{BASE}/api/max/market/snapshot?symbols=BTC,ETH,SOL",
},
{
"id": "spot_ohlcv",
"user_wants": "Get spot candlestick OHLCV data for charts",
"keywords": ["ohlcv", "candles", "klines", "chart", "historical spot"],
"method": "GET",
"path": "/api/max/trading/ohlcv/{symbol}",
"query_params": {"interval": "1h", "limit": "100"},
"path_params": {"symbol": "BTC"},
"returns": "candles[{time,open,high,low,close,volume}], source binance_spot|kucoin_spot|...",
"example_url": "{BASE}/api/max/trading/ohlcv/BTC?interval=1h&limit=100",
},
{
"id": "orderbook",
"user_wants": "Get live order book bids and asks",
"keywords": ["orderbook", "order book", "bids", "asks", "depth"],
"method": "GET",
"path": "/api/max/trading/orderbook/{symbol}",
"query_params": {"limit": "50"},
"path_params": {"symbol": "BTC"},
"returns": "bids, asks, source",
"example_url": "{BASE}/api/max/trading/orderbook/BTC?limit=50",
},
{
"id": "futures_snapshot",
"user_wants": "Get futures mark price, funding rate, and open interest",
"keywords": ["futures", "mark price", "funding", "open interest", "perpetual"],
"method": "GET",
"path": "/api/futures/market/snapshot/{symbol}",
"query_params": {"persist": "true"},
"path_params": {"symbol": "BTC"},
"returns": "mark_price, funding_rate, open_interest, volume_24h, provider kucoin_futures",
"example_url": "{BASE}/api/futures/market/snapshot/BTC",
},
{
"id": "futures_ohlcv_live",
"user_wants": "Get live futures candlestick data",
"keywords": ["futures candles", "futures ohlcv", "futures klines"],
"method": "GET",
"path": "/api/futures/market/ohlcv/{symbol}",
"query_params": {"interval": "1h", "limit": "50"},
"path_params": {"symbol": "BTC"},
"returns": "candles[], saved_to_db count, provider",
"example_url": "{BASE}/api/futures/market/ohlcv/BTC?interval=1h&limit=50",
},
{
"id": "futures_ohlcv_from_db",
"user_wants": "Read stored futures candles from database (no live fetch)",
"keywords": ["futures history", "cached futures", "database candles"],
"method": "GET",
"path": "/api/futures/market/history/{symbol}",
"query_params": {"interval": "1h", "limit": "100"},
"path_params": {"symbol": "BTC"},
"returns": "candles[] from SQLite table cached_futures_ohlc",
"example_url": "{BASE}/api/futures/market/history/BTC?interval=1h&limit=100",
},
{
"id": "futures_sync_db",
"user_wants": "Force fetch futures snapshot + OHLCV and save to database",
"keywords": ["sync futures", "save futures", "persist futures"],
"method": "POST",
"path": "/api/futures/market/sync/{symbol}",
"query_params": {"interval": "1h", "limit": "50"},
"path_params": {"symbol": "BTC"},
"returns": "snapshot + ohlcv payloads, both persisted",
"example_url": "{BASE}/api/futures/market/sync/BTC?interval=1h&limit=50",
},
{
"id": "futures_validate_kucoin",
"user_wants": "Validate KuCoin futures contract exists and is tradeable",
"keywords": ["kucoin futures", "contract validate", "leverage", "xbtusdtm"],
"method": "GET",
"path": "/api/max/futures/kucoin/validate/{symbol}",
"query_params": {},
"path_params": {"symbol": "BTC"},
"returns": "validated, contract, markPrice, maxLeverage",
"example_url": "{BASE}/api/max/futures/kucoin/validate/BTC",
},
{
"id": "indicators_comprehensive",
"user_wants": "Get RSI, MACD, Bollinger Bands and overall signal for one symbol",
"keywords": ["indicators", "rsi", "macd", "bollinger", "technical analysis", "signals"],
"method": "GET",
"path": "/api/max/indicators/comprehensive",
"query_params": {"symbol": "BTC", "timeframe": "1h"},
"path_params": {},
"returns": "rsi, macd, bollinger_bands, overall signal BUY|SELL|HOLD",
"example_url": "{BASE}/api/max/indicators/comprehensive?symbol=BTC&timeframe=1h",
},
{
"id": "indicator_single",
"user_wants": "Get one technical indicator only",
"keywords": ["rsi only", "macd only", "single indicator"],
"method": "GET",
"path": "/api/max/indicators/{indicator_id}",
"query_params": {"symbol": "BTC", "timeframe": "1h"},
"path_params": {"indicator_id": "rsi"},
"returns": "indicator-specific values; indicator_id: rsi|macd|bollinger_bands|sma|ema|...",
"example_url": "{BASE}/api/max/indicators/rsi?symbol=BTC&timeframe=1h",
},
{
"id": "indicators_batch",
"user_wants": "Analyze multiple symbols or indicators in one POST",
"keywords": ["batch indicators", "analyze many", "bulk technical"],
"method": "POST",
"path": "/api/max/indicators/analyze",
"query_params": {},
"path_params": {},
"body_json": {"symbols": ["BTC", "ETH"], "timeframe": "1h", "indicators": ["rsi", "macd"]},
"returns": "results per symbol",
"example_url": "{BASE}/api/max/indicators/analyze",
},
{
"id": "sentiment_fear_greed",
"user_wants": "Get crypto Fear and Greed index and social sentiment",
"keywords": ["sentiment", "fear greed", "fng", "mood", "social"],
"method": "GET",
"path": "/api/max/social/sentiment",
"query_params": {"coin": "BTC"},
"path_params": {},
"returns": "fear_greed value, reddit probe, data_state",
"example_url": "{BASE}/api/max/social/sentiment?coin=BTC",
},
{
"id": "news_crypto",
"user_wants": "Get latest cryptocurrency news articles",
"keywords": ["news", "headlines", "articles", "bitcoin news"],
"method": "GET",
"path": "/api/max/news",
"query_params": {"q": "bitcoin", "limit": "10"},
"path_params": {},
"returns": "items[] with title, url, source; fallback newsapi|cryptocompare|reddit",
"example_url": "{BASE}/api/max/news?q=bitcoin&limit=10",
},
{
"id": "provider_health",
"user_wants": "Check which data providers are working right now",
"keywords": ["providers", "health", "probe", "binance down", "kucoin status"],
"method": "GET",
"path": "/api/max/providers/status",
"query_params": {"symbol": "BTC", "include_slow": "true"},
"path_params": {},
"returns": "providers[] with live_status ok|down, latency_ms",
"example_url": "{BASE}/api/max/providers/status?symbol=BTC&include_slow=true",
},
{
"id": "fallback_chains",
"user_wants": "See fallback order when a provider fails",
"keywords": ["fallback", "failover", "backup provider", "chain"],
"method": "GET",
"path": "/api/max/fallback/plan",
"query_params": {},
"path_params": {},
"returns": "FALLBACK_CHAINS map, binance base rotation",
"example_url": "{BASE}/api/max/fallback/plan",
},
{
"id": "db_collector_status",
"user_wants": "Check automatic 15-minute database collection worker",
"keywords": ["worker", "scheduler", "auto collect", "database sync", "15 minutes"],
"method": "GET",
"path": "/api/worker/comprehensive/status",
"query_params": {},
"path_params": {},
"returns": "is_running, interval_minutes, last_collection, total_records_saved",
"example_url": "{BASE}/api/worker/comprehensive/status",
},
{
"id": "db_collector_run_now",
"user_wants": "Trigger immediate full database collection (market+futures+news+sentiment)",
"keywords": ["collect now", "sync database", "run worker", "save to db"],
"method": "POST",
"path": "/api/worker/comprehensive/run-now",
"query_params": {},
"path_params": {},
"returns": "totals: market, spot_ohlc, futures_snapshots, futures_ohlc, news, sentiment",
"example_url": "{BASE}/api/worker/comprehensive/run-now",
},
{
"id": "capabilities_map",
"user_wants": "Get full capability map for integrating client applications",
"keywords": ["capabilities", "features", "what can this api do"],
"method": "GET",
"path": "/api/max/app/capabilities",
"query_params": {},
"path_params": {},
"returns": "service_matrix, main_app_endpoints, pages",
"example_url": "{BASE}/api/max/app/capabilities",
},
{
"id": "swagger_ui",
"user_wants": "Browse all 250+ endpoints interactively",
"keywords": ["swagger", "openapi", "try api", "interactive docs"],
"method": "GET",
"path": "/docs",
"query_params": {},
"path_params": {},
"returns": "HTML Swagger UI",
"example_url": "{BASE}/docs",
},
]
ALL_ENDPOINTS: List[Dict[str, str]] = [
{"method": "GET", "path": "/api/max/health", "group": "Core", "purpose": "Layer health, registry, cache"},
{"method": "GET", "path": "/api/max/help", "group": "Documentation", "purpose": "This AI-friendly help JSON"},
{"method": "GET", "path": "/api/max/endpoints/catalog", "group": "Documentation", "purpose": "Grouped endpoint catalog"},
{"method": "GET", "path": "/api/max/app/bootstrap", "group": "Main App", "purpose": "Startup bundle for client apps"},
{"method": "GET", "path": "/api/max/app/symbol/{symbol}", "group": "Main App", "purpose": "All-in-one symbol bundle"},
{"method": "GET", "path": "/api/max/app/universe", "group": "Main App", "purpose": "Multi-symbol scanner feed"},
{"method": "GET", "path": "/api/max/app/capabilities", "group": "Main App", "purpose": "Feature and service map"},
{"method": "GET", "path": "/api/max/market/price/{symbol}", "group": "Market", "purpose": "Spot price with fallback"},
{"method": "GET", "path": "/api/max/market/snapshot", "group": "Market", "purpose": "Multi-asset spot snapshot"},
{"method": "GET", "path": "/api/max/trading/ohlcv/{symbol}", "group": "Trading", "purpose": "Spot OHLCV candles"},
{"method": "GET", "path": "/api/max/trading/orderbook/{symbol}", "group": "Trading", "purpose": "Order book"},
{"method": "GET", "path": "/api/futures/market/snapshot/{symbol}", "group": "Futures", "purpose": "Futures mark/funding/OI"},
{"method": "GET", "path": "/api/futures/market/ohlcv/{symbol}", "group": "Futures", "purpose": "Live futures OHLCV + DB save"},
{"method": "GET", "path": "/api/futures/market/history/{symbol}", "group": "Futures", "purpose": "Futures candles from SQLite"},
{"method": "POST", "path": "/api/futures/market/sync/{symbol}", "group": "Futures", "purpose": "Force futures fetch + persist"},
{"method": "GET", "path": "/api/max/futures/market/{symbol}", "group": "Futures", "purpose": "Futures snapshot via max layer"},
{"method": "GET", "path": "/api/max/futures/ohlcv/{symbol}", "group": "Futures", "purpose": "Futures OHLCV via max layer"},
{"method": "GET", "path": "/api/max/futures/kucoin/validate/{symbol}", "group": "Futures", "purpose": "KuCoin contract validation"},
{"method": "GET", "path": "/api/max/indicators/services", "group": "Indicators", "purpose": "Indicator catalog"},
{"method": "GET", "path": "/api/max/indicators/comprehensive", "group": "Indicators", "purpose": "RSI+MACD+BB bundle"},
{"method": "GET", "path": "/api/max/indicators/{indicator_id}", "group": "Indicators", "purpose": "Single indicator"},
{"method": "POST", "path": "/api/max/indicators/analyze", "group": "Indicators", "purpose": "Batch indicator analysis"},
{"method": "GET", "path": "/api/max/social/sentiment", "group": "Sentiment", "purpose": "Fear & Greed + Reddit"},
{"method": "GET", "path": "/api/max/news", "group": "News", "purpose": "News with fallback chain"},
{"method": "GET", "path": "/api/max/providers", "group": "Providers", "purpose": "All provider definitions"},
{"method": "GET", "path": "/api/max/providers/status", "group": "Providers", "purpose": "Live provider probes"},
{"method": "GET", "path": "/api/max/providers/test/{provider_id}", "group": "Providers", "purpose": "Test one provider"},
{"method": "GET", "path": "/api/max/fallback/plan", "group": "Operations", "purpose": "Fallback chain map"},
{"method": "GET", "path": "/api/max/pressure/status", "group": "Operations", "purpose": "Rate-limit / cooldown state"},
{"method": "GET", "path": "/api/max/cache/status", "group": "Operations", "purpose": "In-memory cache stats"},
{"method": "GET", "path": "/api/worker/comprehensive/config", "group": "Database Worker", "purpose": "15-min collector settings"},
{"method": "GET", "path": "/api/worker/comprehensive/status", "group": "Database Worker", "purpose": "Collector run stats"},
{"method": "POST", "path": "/api/worker/comprehensive/run-now", "group": "Database Worker", "purpose": "Immediate DB sync"},
{"method": "GET", "path": "/api/worker/status", "group": "Database Worker", "purpose": "Legacy background worker stats"},
{"method": "GET", "path": "/health", "group": "Core", "purpose": "Simple alive check"},
{"method": "GET", "path": "/docs", "group": "Documentation", "purpose": "Swagger UI (250+ routes)"},
{"method": "GET", "path": "/openapi.json", "group": "Documentation", "purpose": "Full OpenAPI spec"},
]
AI_AGENT_INSTRUCTIONS: Dict[str, Any] = {
"read_this_first": (
"You are calling a cryptocurrency datasource API on Hugging Face Spaces. "
"Always replace {BASE} with the deployment URL (e.g. https://really-amin-datasourceforcryptocurrency-1.hf.space). "
"Start with GET {BASE}/api/max/help if you are unsure which endpoint to use."
),
"query_algorithm": [
"1. Read the user question and extract keywords (symbol, data type: price/ohlcv/futures/news/sentiment/indicators).",
"2. Search intent_map[] for matching keywords or user_wants text (case-insensitive).",
"3. Pick the best intent id. Build URL: {BASE} + path with path_params substituted.",
"4. Add query_params to the URL. Use GET unless method is POST.",
"5. For POST endpoints, send Content-Type: application/json and use body_json from the intent.",
"6. If no intent matches, call GET {BASE}/api/max/app/symbol/{SYMBOL} for a combined answer.",
"7. Set HTTP timeout to at least 30 seconds (HF Spaces cold start can take 60s).",
"8. Check response field data_state: REAL means live data, UNAVAILABLE means all providers failed.",
],
"recommended_entrypoints": {
"simplest_health": "GET /api/max/health",
"best_single_symbol": "GET /api/max/app/symbol/BTC",
"best_futures": "GET /api/futures/market/snapshot/BTC",
"best_indicators": "GET /api/max/indicators/comprehensive?symbol=BTC&timeframe=1h",
"best_news": "GET /api/max/news?q=bitcoin&limit=10",
"best_sentiment": "GET /api/max/social/sentiment?coin=BTC",
"full_endpoint_list": "GET /api/max/endpoints/catalog",
},
"symbol_rules": {
"spot_price_path": "Use base asset: BTC, ETH, SOL (not BTCUSDT required on /api/max/market/price/{symbol})",
"ohlcv_path": "Accepts BTC or BTCUSDT on /api/max/trading/ohlcv/{symbol}",
"futures_path": "Use base asset BTC on /api/futures/market/* — server maps to XBTUSDTM on KuCoin",
},
"response_fields": {
"success": "boolean — request completed without server error",
"data_state": "REAL | CACHED_DB | UNAVAILABLE — never treat UNAVAILABLE as real market data",
"provider": "which exchange/source returned the data",
"attempts": "list of tried providers when fallback was used",
},
}
DATABASE_TABLES: List[Dict[str, str]] = [
{"table": "cached_market_data", "contains": "Spot prices saved by background collector", "read_via": "Internal; use /api/max/market/price for live"},
{"table": "cached_ohlc", "contains": "Spot OHLC candles", "read_via": "/api/ohlcv or /api/max/trading/ohlcv"},
{"table": "cached_futures_snapshot", "contains": "Futures mark price, funding, OI snapshots", "read_via": "/api/futures/market/snapshot or history"},
{"table": "cached_futures_ohlc", "contains": "Futures OHLC candles", "read_via": "/api/futures/market/history/{symbol}"},
{"table": "news_articles", "contains": "Collected news articles", "read_via": "/api/news/latest or /api/max/news"},
{"table": "sentiment_metrics", "contains": "Fear & Greed and other sentiment metrics", "read_via": "/api/max/social/sentiment"},
{"table": "market_prices", "contains": "Historical spot price rows", "read_via": "Internal time-series"},
]
WORKERS: List[Dict[str, Any]] = [
{
"name": "Comprehensive DB Collector",
"interval_minutes": 15,
"env_enable": "COMPREHENSIVE_DB_COLLECTOR_ENABLED=true",
"collects": ["market prices", "spot OHLC", "futures snapshot", "futures OHLC", "news", "sentiment"],
"database": "data/api_monitor.db",
"status_api": "/api/worker/comprehensive/status",
"run_now_api": "POST /api/worker/comprehensive/run-now",
},
{
"name": "Legacy Background Worker",
"interval_minutes": "5 UI + 15 historical",
"database": "data/crypto_data.db",
"status_api": "/api/worker/status",
},
]
PRODUCT_TIERS: List[Dict[str, Any]] = [
{"tier": "Basic", "includes": ["spot price", "fear & greed", "/api/max/health"]},
{"tier": "Trader", "includes": ["Basic", "OHLCV", "indicators", "futures snapshot", "orderbook"]},
{"tier": "Pro", "includes": ["Trader", "news", "DB futures history", "provider status"]},
{"tier": "Enterprise", "includes": ["Pro", "/api/max/app/* bundles", "comprehensive DB worker", "batch indicators"]},
]
def build_endpoint_catalog() -> Dict[str, Any]:
groups: Dict[str, List[Dict[str, str]]] = {}
for item in ALL_ENDPOINTS:
groups.setdefault(item["group"], []).append(item)
return {
"success": True,
"base_prefix": "/api/max",
"total": len(ALL_ENDPOINTS),
"groups": groups,
"endpoints": ALL_ENDPOINTS,
"swagger": "/docs",
"openapi": "/openapi.json",
"timestamp": _now_iso(),
}
def build_api_help_payload(base_url: str = DEFAULT_BASE) -> Dict[str, Any]:
"""Full payload returned by GET /api/max/help."""
catalog = build_endpoint_catalog()
payload = {
"success": True,
"schema_version": "2.0",
"language": "en",
"title": "Crypto Datasource API — AI Agent Help Guide",
"summary": (
"Machine-readable guide for LLMs and simple AI agents. "
"Use intent_map to map natural-language questions to HTTP endpoints. "
"All market data is REAL from exchanges — never synthetic."
),
"base_url": base_url,
"base_url_placeholder": "{BASE}",
"for_ai_agents": AI_AGENT_INSTRUCTIONS,
"intent_map": INTENT_MAP,
"intent_count": len(INTENT_MAP),
"quick_examples": {
"health": f"curl {base_url}/api/max/health",
"symbol_bundle": f"curl {base_url}/api/max/app/symbol/BTC",
"futures_snapshot": f"curl {base_url}/api/futures/market/snapshot/BTC",
"futures_ohlcv": f"curl '{base_url}/api/futures/market/ohlcv/BTC?interval=1h&limit=50'",
"indicators": f"curl '{base_url}/api/max/indicators/comprehensive?symbol=BTC&timeframe=1h'",
"news": f"curl '{base_url}/api/max/news?q=bitcoin&limit=10'",
"sentiment": f"curl '{base_url}/api/max/social/sentiment?coin=BTC'",
"db_collect_now": f"curl -X POST {base_url}/api/worker/comprehensive/run-now",
"catalog": f"curl {base_url}/api/max/endpoints/catalog",
},
"catalog": catalog,
"database_tables": DATABASE_TABLES,
"workers": WORKERS,
"product_tiers": PRODUCT_TIERS,
"ui_pages": [
{"route": "/help", "purpose": "This guide (human + loads /api/max/help)"},
{"route": "/market", "purpose": "Live market dashboard"},
{"route": "/services", "purpose": "Indicator services + main-app API links"},
{"route": "/technical-analysis", "purpose": "Charts and TA"},
{"route": "/trading-assistant", "purpose": "Trading tools"},
{"route": "/news", "purpose": "News feed"},
{"route": "/sentiment", "purpose": "Sentiment dashboard"},
{"route": "/api-explorer", "purpose": "Try APIs in browser"},
{"route": "/system-monitor", "purpose": "Provider visual graph"},
],
"important_rules": [
"Never fabricate prices if data_state is UNAVAILABLE — report failure to the user.",
"Prefer /api/max/app/symbol/{symbol} when the user asks for 'everything about BTC'.",
"Futures primary provider is KuCoin (US-safe); Binance fapi may be geo-blocked on HF US.",
"First request after Space sleep may take 30-60 seconds — use timeout>=60.",
"POST /api/futures/market/sync/{symbol} persists data; GET history reads from DB.",
"Comprehensive DB collector runs every 15 minutes when COMPREHENSIVE_DB_COLLECTOR_ENABLED=true.",
],
"common_errors": [
{"http": 404, "fix": "Call GET /api/max/endpoints/catalog or /openapi.json to verify path"},
{"http": 503, "fix": "All providers in chain failed; check GET /api/max/providers/status"},
{"http": 422, "fix": "POST body schema wrong — see body_json on the intent_map entry"},
{"symptom": "Empty futures history", "fix": "Run POST /api/worker/comprehensive/run-now or POST /api/futures/market/sync/BTC first"},
],
"related_files": {
"json_mirror": "api-resources/ai_api_help_guide.json",
"human_help_page": "/help",
"swagger": "/docs",
},
"timestamp": _now_iso(),
}
return payload
def write_guide_json_file(base_url: str = DEFAULT_BASE) -> Path:
"""Persist guide to api-resources for static download / git visibility."""
payload = build_api_help_payload(base_url=base_url)
GUIDE_JSON_PATH.parent.mkdir(parents=True, exist_ok=True)
GUIDE_JSON_PATH.write_text(json.dumps(payload, indent=2, ensure_ascii=False), encoding="utf-8")
return GUIDE_JSON_PATH