Documentation · v0.3.0

Market Oracle API

Reference for integrating bots and AI agents. At the top — a quick-start foundation; below — the full set of endpoints, limits, errors, and data contracts.

Purpose

Market Oracle is a market data source only. It does not open trades or manage positions. Between exchanges and clients sits a single prepared layer: closed bars, indicators, order-book facts, macro, and market regime.

Core rule: trading decisions — only on a closed 1m bar (closed: true, bar −1). Signal deduplication: symbol:ts.

Quick start

1. Health

Check status=ok, Redis, and WS provider.

GET /health

2. Plan

Limits: daily / RPM / WS / expires_at.

GET /v1/me

3. Symbols

Take only ready=true.

GET /v1/symbols

4. Stream

Subscribe to closed bars.

WS /v1/stream

5. Context

Snapshot before a decision (60–90 s).

GET /v1/context/{symbol}

6. Signal

Once per closed bar.

dedupe symbol:ts
# Example (substitute your BASE and key) curl.exe -s https://HOST/health curl.exe -s https://HOST/v1/me -H "Authorization: Bearer mo_…" curl.exe -s "https://HOST/v1/context/BTCUSDT" -H "Authorization: Bearer mo_…"

Authorization

All /v1/* routes require the header:

Authorization: Bearer mo_…

Symbol readiness

FieldWhereMeaning
bars_1m / bar_countsymbols, statushow many 1m bars in Redis
readysymbols, status, contexttrue at ≥ 200 bars (EMA200 warmup)
historysamewarming / ready / full_day (≥1440)
indicators_readylatest, status, contextbase set ema20+rsi14+atr14 present
data_quality.scorecontext, status0…100; for entry require ≥ 70
lag_secstatus, contextage of closed bar; >120 cuts score to ≤69
Important: readyindicators_ready. For EMA200 you need both. Don't trade a "warm" pair with 15 candles as if it were BTC with a full day of history.

GET /v1/context/{symbol}

Main endpoint for bots/AI. One response instead of 8–10 calls:

BlockPurpose
bar + indicatorssignal only on closed 1m
ticker24h volume/change, best bid/ask
depthspread, imbalance, walls (live snapshot)
ready / history / lag_secwhether the pair is tradeable
macro_event_soonpause before FOMC/CPI (high impact <60 min)
derivatives + liquidationsfunding / OI / cascades
macro_snapshotF&G, dominance, stables, DXY/10Y
cross_exchangevenue consensus, divergence
market_regimecorr to BTC, vol, breadth
data_qualityscore + flags

Not in context (request separately): long history, event calendar, live WS, /v1/meta, closed minute microstructure history.

Limitation: context_scope="live_snapshot", historical_safe=false — this is not point-in-time history for backtesting.

WebSocket /v1/stream

ws(s)://HOST/v1/stream # or ws(s)://HOST/v1/stream?token=mo_…
  1. After connect the server sends {"type":"hello",…}
  2. Client: {"op":"subscribe","symbols":["*"]} or a pair list
  3. For order book: "microstructure": true → extra microstructure_close event
  4. Signal event: {"type":"bar_close","symbol":"BTCUSDT","bar":{…},"interval":"1m"}
  5. Ping: {"op":"ping"}pong

Join bar_close and microstructure_close strictly by symbol + ts, not by receive time. WS push does not spend daily quota.

Plans and limits

PlanRequests / dayRPMMin. pauseMax WS
free6 000302 s (2000 ms)1
basic25 000120500 ms2
pro100 000180350 ms3

Pause between requests ≈ 60 000 ms ÷ RPM (steady pace under the per-minute limit). Heavy endpoints (context/history = weight 3) spend more of the daily quota; /v1/me, /v1/symbols, /v1/meta/*, /v1/calendar — weight 0 for the day (RPM and pause still apply). WS push does not spend daily quota.

On limit: HTTP 429, headers X-RateLimit-*, Retry-After, X-Quota-*. Check the status/code field in the body.

Practice: on basiccontext every 60–90 s per active pair; on free — less often (6k/day budget). Don't storm with dozens of parallel context calls.

All endpoints

Service

MethodPathDescription
GET/health, /v1/healthstatus, Redis, active_provider, failover
GET/metricsPrometheus text
GET/v1/mekey plan, usage, weights, expires_at

Keys (admin)

MethodPathDescription
GET / POST/v1/keyslist / create (name, tier, expires_at)
PATCH / DELETE/v1/keys/{id}change tier/expiry / revoke

Symbols and status

MethodPathDescription
GET/v1/symbolsactive pairs + bars / ready / history
POST/v1/symbolsadd pair → bootstrap + WS reload
DELETE/v1/symbols/{symbol}remove from registry
GET/v1/status/{symbol}lag, ready, indicators, quality
GET/v1/meta/{symbol}tick / step / minNotional

History and sync

MethodPathDescription
GET/v1/history/{symbol}?interval=1m|1h|4h|1d|1w, limit, from, to
POST/v1/history/batchup to 20 pairs; optional include_microstructure
POST/v1/sync/bootstrapcold dump from Redis for the client
GET/v1/latest?symbols=last closed bar + ticker
GET/v1/indicators/{symbol}indicators only over history
IntervalDepthIndicators
1m21 days (live WS)yes
1h~9 mono (null)
4h2 yearsno
1d3 yearsno
1w5 yearsno

Market slice

MethodPathDescription
GET/v1/context/{symbol}full AI snapshot
GET/v1/depth/{symbol}live top-20 / recent seconds (execution filter)
GET/v1/derivatives/{symbol}funding, OI, liquidations
GET/v1/calendar?hours=, ?high_only=true
GET/v1/macroF&G (+history ?fng_days=), dominance, stables, FRED
GET/v1/quotes/{symbol}BBO consensus Binance/Bybit/OKX
GET/v1/market-regimecorr / vol / breadth from own 1h

Microstructure

MethodPathDescription
GET/v1/microstructure/{symbol}closed minute order-book history
GET/v1/microstructure/{symbol}/latestlast closed minute

Top-20 aggregation @ 1 Hz into a UTC minute. Live depth in context and closed microstructure are different entities. Historical depth from the exchange is not reconstructed after the fact.

Indicators on the 1m bar

Incremental computation, batch-reference tests. Fields are decimal strings; may be null during warmup.

Errors and statuses

status / codeHTTPWhen
ok200success
key_missing / key_invalid / key_expired / key_revoked401key problems
unauthorized401wrong admin token
rate_limited / quota_exceeded / too_fast / ws_limit429plan limits
unavailable503auth/DB temporarily unavailable

Client: check status (or code) first; don't parse the error text. After 429 — sleep for retry_after_ms / Retry-After.

Checklist for an AI agent / bot

  1. GET /healthstatus == "ok", Redis ok, WS connected.
  2. GET /v1/me → account for tier, daily, RPM, min_interval_ms, expires_at.
  3. GET /v1/symbols → filter ready == true (prefer full_day).
  4. WS subscribe; for order book — microstructure: true.
  5. On bar_close — analyze once (dedupe symbol:ts).
  6. Before entry / on schedule — GET /v1/context/{symbol}; gate: data_quality.score ≥ 70, ready, indicators_ready.
  7. Optionally 1–2 s after signal: GET /v1/depth/{symbol}?seconds=3 as an execution filter (does not change the historical bar signal).
  8. After reconnect: pause ≥ min_interval → /v1/history (+ microstructure) → exact join.
  9. Don't store the admin token in the client. Don't publish mo_… in a repository.
Source of truth in the repo: docs/DOC.md, docs/AUTH.md, docs/agents.md. This page is a public digest of the same specification.