Spaces:
Sleeping
Sleeping
| # API Reference | |
| ## Base and authentication | |
| All Futures routes are mounted on the existing Hermes FastAPI application and port. In production, use the Space base URL and an authenticated browser/session or HTTP Basic credentials. | |
| When `HERMES_ADMIN_PASSWORD` is set, Futures API routes require: | |
| ```http | |
| Authorization: Basic <base64(username:password)> | |
| ``` | |
| Default username: `admin`, configurable with `HERMES_DASHBOARD_BASIC_AUTH_USERNAME`. | |
| All Futures responses set `Cache-Control: no-store`. `/futures` also sets no-cache headers and runtime SHA-256 headers. | |
| ## `GET /futures` | |
| Returns the packaged HTML dashboard. | |
| Important response headers: | |
| ```text | |
| X-Hermes-Template-SHA256 | |
| X-Hermes-Router-SHA256 | |
| Cache-Control: no-store, no-cache, must-revalidate, max-age=0 | |
| ``` | |
| ## `GET /api/futures/status` | |
| Returns application status, runtime-file evidence, market health, latest bounded plan state, source metadata, account summary, and diagnostics. | |
| Representative shape: | |
| ```json | |
| { | |
| "application": { | |
| "status": "online", | |
| "runtimeStatus": "verified | mismatch | unknown", | |
| "runtimeFiles": {} | |
| }, | |
| "marketData": {"status": "healthy | degraded | unavailable"}, | |
| "tradingReadiness": "ready | blocked", | |
| "mergeStatus": "complete | partial | unknown", | |
| "analysisState": "NOT_ANALYZED", | |
| "sourceMetadata": { | |
| "datasource4": {}, | |
| "binance": {}, | |
| "datasource2": {} | |
| }, | |
| "fieldSources": {}, | |
| "fieldMetadata": {}, | |
| "verifiedFutures": false, | |
| "missingRequiredFields": [], | |
| "staleRequiredFields": [], | |
| "latestTradePlan": null, | |
| "latestPlanId": null, | |
| "latestSignalScore": null, | |
| "riskApproved": false, | |
| "tradingMode": "paper", | |
| "equity": 10000.0, | |
| "realizedPnlToday": 0.0, | |
| "openPositionCount": 0, | |
| "serverTime": 0 | |
| } | |
| ``` | |
| Consumers should treat additional fields as additive and avoid strict whole-object equality. | |
| ## `GET /api/futures/symbols` | |
| Returns the merged catalog. | |
| ```json | |
| { | |
| "symbols": [ | |
| { | |
| "symbol": "BTCUSDT", | |
| "baseAsset": "BTC", | |
| "quoteAsset": "USDT", | |
| "futuresVerified": true, | |
| "marketOnly": false, | |
| "contractType": "PERPETUAL", | |
| "status": "TRADING", | |
| "source": "datasource4", | |
| "rank": 1, | |
| "updatedAt": "2026-07-21T00:00:00Z" | |
| } | |
| ], | |
| "source": "...", | |
| "updatedAt": "...", | |
| "counts": { | |
| "total": 0, | |
| "verifiedFutures": 0, | |
| "marketOnly": 0 | |
| } | |
| } | |
| ``` | |
| Catalog membership alone does not authorize execution. Only items with `futuresVerified=true` are eligible for Paper revalidation. | |
| ## `GET /api/futures/positions` | |
| Returns Paper mode and enriched open positions. | |
| ```json | |
| { | |
| "mode": "paper", | |
| "positions": [ | |
| { | |
| "symbol": "BTC/USDT:USDT", | |
| "side": "long", | |
| "size": 0.01, | |
| "entryPrice": 60000.0, | |
| "markPrice": 60500.0, | |
| "unrealizedPnl": 5.0 | |
| } | |
| ] | |
| } | |
| ``` | |
| Mark price enrichment is best-effort. Missing mark data produces `null`, not zero. | |
| ## `GET /api/futures/market` | |
| Query parameters: | |
| | Parameter | Type | Default | Constraints | | |
| |---|---|---:|---| | |
| | `symbol` | string | `BTCUSDT` | length 3–32; normalized server-side | | |
| | `interval` | enum | `5m` | `1m`, `5m`, `15m`, `1h` | | |
| | `limit` | integer | `120` | 20–500 | | |
| Example: | |
| ```http | |
| GET /api/futures/market?symbol=BTCUSDT&interval=5m&limit=120 | |
| ``` | |
| Successful/partial shape: | |
| ```json | |
| { | |
| "state": "available | partial | stale | unavailable", | |
| "analysisState": "NOT_ANALYZED | STALE | API_UNAVAILABLE", | |
| "dataUsability": "usable | degraded | unavailable", | |
| "reason": null, | |
| "symbol": "BTCUSDT", | |
| "interval": "5m", | |
| "limit": 120, | |
| "candles": [ | |
| {"timestamp": 0, "open": 0, "high": 0, "low": 0, "close": 0, "volume": 0} | |
| ], | |
| "currentPrice": null, | |
| "markPrice": null, | |
| "change24h": null, | |
| "volume24h": null, | |
| "fundingRate": null, | |
| "openInterest": null, | |
| "source": "datasource4 | binance_public | datasource2 | mixed | unavailable", | |
| "sourcesUsed": [], | |
| "fieldSources": {}, | |
| "fieldMetadata": {}, | |
| "freshness": "fresh | stale | invalid | unknown", | |
| "verifiedFutures": false, | |
| "futuresVerification": {}, | |
| "warnings": [], | |
| "missingFields": [], | |
| "analysisRequiredFieldsMissing": [], | |
| "staleRequiredFields": [], | |
| "mergeStatus": "complete | partial | unavailable", | |
| "tradingReadiness": "ready | blocked", | |
| "rejectionReasons": [], | |
| "sourceMetadata": {}, | |
| "technicalDiagnostics": {}, | |
| "fetchedAt": 0 | |
| } | |
| ``` | |
| If acquisition raises, the route returns HTTP `503` with the same high-level keys, empty candles, null values, `state=unavailable`, `analysisState=API_UNAVAILABLE`, and blocked readiness. | |
| No mock candles are permitted in production responses. | |
| ## `GET /api/futures/trade-plan` | |
| Query parameters: | |
| | Parameter | Type | Required | Constraints | | |
| |---|---|---:|---| | |
| | `symbol` | string | yes | length 3–32; normalized server-side | | |
| Returns the latest durable Paper plan for the authenticated owner and symbol. When no plan exists, the route still returns HTTP `200` with null plan fields so the SPA can distinguish an empty feed from a missing route. | |
| ```json | |
| { | |
| "symbol": "BTCUSDT", | |
| "plan": {}, | |
| "tradePlan": {}, | |
| "latestTradePlan": {} | |
| } | |
| ``` | |
| Plan objects match the bounded analyze response shape, including `planId`, `decision`, geometry, and risk metadata. | |
| ## `GET /api/futures/signals` | |
| Query parameters: | |
| | Parameter | Type | Required | Constraints | | |
| |---|---|---:|---| | |
| | `symbol` | string | yes | length 3–32 | | |
| Returns deterministic signal components from the latest durable plan for the authenticated owner. | |
| ```json | |
| { | |
| "symbol": "BTCUSDT", | |
| "components": {}, | |
| "signalComponents": {} | |
| } | |
| ``` | |
| ## `GET /api/futures/advisory` | |
| Query parameters: | |
| | Parameter | Type | Required | Constraints | | |
| |---|---|---:|---| | |
| | `symbol` | string | yes | length 3–32 | | |
| Returns the latest optional AI context record for the symbol when `EXTERNAL_AI_ENABLED` is on. Advisory output is informational only and never changes deterministic analysis. Records are sourced from the authenticated owner's latest durable plan (`external_advisory` field). | |
| When advisory is disabled or no plan exists, `advisory` and `external_advisory` are `null` and `enabled` reflects configuration. | |
| When present, advisory objects follow `external_ai/advisory_schema.py` plus runtime metadata: | |
| ```json | |
| { | |
| "symbol": "BTCUSDT", | |
| "enabled": true, | |
| "advisory": { | |
| "advisory_id": "hex", | |
| "status": "available", | |
| "provider": "hermes_auxiliary", | |
| "model": "futures_advisory", | |
| "market_bias": "bullish", | |
| "confidence": 0.62, | |
| "summary": "…", | |
| "supporting_points": ["…"], | |
| "risk_warnings": ["…"], | |
| "latency_ms": 420, | |
| "fallback_used": false, | |
| "error": null, | |
| "attempts": [ | |
| { | |
| "provider": "hermes_auxiliary", | |
| "model": "futures_advisory", | |
| "latency_ms": 420, | |
| "error": null, | |
| "status": "succeeded" | |
| } | |
| ], | |
| "provider_order": ["futures_advisory"] | |
| }, | |
| "external_advisory": { } | |
| } | |
| ``` | |
| `status` is `available` or `unavailable`. Unavailable records may include `error` (for example `disabled`, `timeout`, `invalid_advisory`). | |
| ## `GET /api/futures/activity` | |
| Query parameters: | |
| | Parameter | Type | Default | Constraints | | |
| |---|---|---:|---| | |
| | `limit` | integer | `50` | 1–200 | | |
| Returns sanitized recent audit events for the authenticated dashboard owner. | |
| ```json | |
| { | |
| "items": [ | |
| { | |
| "type": "plan_superseded", | |
| "event": "plan_superseded", | |
| "message": "Plan superseded by abc123", | |
| "timestamp": 0, | |
| "created_at": 0, | |
| "time": "2026-07-24T00:00:00Z" | |
| } | |
| ], | |
| "events": [], | |
| "activity": [], | |
| "limit": 50 | |
| } | |
| ``` | |
| ## `POST /api/futures/analyze` | |
| Request: | |
| ```json | |
| { | |
| "symbol": "BTCUSDT", | |
| "risk_profile": "moderate", | |
| "include_external_context": false | |
| } | |
| ``` | |
| Allowed risk profiles: | |
| ```text | |
| conservative | |
| moderate | |
| aggressive | |
| ``` | |
| Unknown request fields are rejected. | |
| Representative response: | |
| ```json | |
| { | |
| "planId": "server-generated-reference", | |
| "symbol": "BTCUSDT", | |
| "decision": "LONG | SHORT | NO_TRADE", | |
| "analysis_state": "LONG | SHORT | NO_TRADE", | |
| "score": null, | |
| "confidence": null, | |
| "components": {}, | |
| "core_reasons": [], | |
| "warnings": [], | |
| "entry": null, | |
| "stop_loss": null, | |
| "take_profit": null, | |
| "reward_to_risk": null, | |
| "risk_profile": "moderate", | |
| "risk_percent": null, | |
| "requested_leverage": 5, | |
| "effective_leverage": null, | |
| "quantity": null, | |
| "estimated_slippage_percent": null, | |
| "risk_approved": false, | |
| "rejection_reasons": [], | |
| "noTradeGuard": true, | |
| "plan_type": "directional_plan | non_executable_plan", | |
| "executable": false, | |
| "futuresVerified": false, | |
| "trading_readiness": "blocked", | |
| "created_at": "...", | |
| "expires_at": "...", | |
| "external_advisory": null | |
| } | |
| ``` | |
| A `NO_TRADE` response is a successful deterministic evaluation, not an HTTP failure. An internal analysis failure returns HTTP `503` with `detail="Futures analysis failed"` and clears the current plan state. | |
| ## `POST /api/futures/paper/execute` | |
| Request: | |
| ```json | |
| { | |
| "symbol": "BTCUSDT", | |
| "risk_profile": "moderate", | |
| "planId": "server-generated-reference" | |
| } | |
| ``` | |
| The endpoint may return: | |
| - `403` for unverified contract or non-Paper mode; | |
| - `409` for superseded/unknown plan, symbol/risk change, expiry, prior execution, blocked readiness, failed fresh revalidation, or non-executable plan; | |
| - `422` for invalid request shape/symbol; | |
| - `200` for the final Paper result. | |
| The endpoint is intentionally absent from the read-only audit tool. | |
| ## Telegram routes | |
| ### `POST /api/telegram/webhook` | |
| Public webhook ingress protected by: | |
| ```http | |
| X-Telegram-Bot-Api-Secret-Token: <TELEGRAM_WEBHOOK_SECRET> | |
| ``` | |
| Limits request body to 256 KiB, applies per-user rate limiting, requires owner/allowed-user authorization, and invokes analysis-only commands. | |
| ### `GET /api/telegram/status` | |
| Returns enabled/mode/webhook/proxy/relay/authorized-user/alert-scheduler status. It does not expose tokens or user IDs. | |
| ### `GET /api/telegram/bootstrap/status` | |
| Requires the same Telegram secret header and returns only: | |
| ```json | |
| {"ok": true, "ownerClaimed": true, "bootstrapConsumed": true} | |
| ``` | |