Spaces:
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:
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:
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:
{
"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.
{
"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.
{
"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:
GET /api/futures/market?symbol=BTCUSDT&interval=5m&limit=120
Successful/partial shape:
{
"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.
{
"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.
{
"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:
{
"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.
{
"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:
{
"symbol": "BTCUSDT",
"risk_profile": "moderate",
"include_external_context": false
}
Allowed risk profiles:
conservative
moderate
aggressive
Unknown request fields are rejected.
Representative response:
{
"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:
{
"symbol": "BTCUSDT",
"risk_profile": "moderate",
"planId": "server-generated-reference"
}
The endpoint may return:
403for unverified contract or non-Paper mode;409for superseded/unknown plan, symbol/risk change, expiry, prior execution, blocked readiness, failed fresh revalidation, or non-executable plan;422for invalid request shape/symbol;200for 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:
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:
{"ok": true, "ownerClaimed": true, "bootstrapConsumed": true}