Gateway contract and schema surface¶
Every consumer of ONIX's backend — the frontend, MCP, and any downstream tool — reads through one
versioned contract: the /v2 gateway (spine.gateway_v2), backed by a generated, digest-pinned
set of JSON Schemas. This page summarizes the shape of that contract; it does not reproduce every
schema.
Wire conventions¶
Every response body is JSON with a top-level version: "spine.v2" field; errors are
{"version": "spine.v2", "error": {"code": <int>, "detail": <string>}}. Money and quantities are
decimal strings, never floats; all timestamps are nanosecond epoch strings; instrument ids
are canonical Nautilus SYMBOL.VENUE strings (see
venues/instrument-identity.md); pagination is opaque-cursor
(cursor/limit in, next_cursor — null when exhausted — out). Canonical JSON (sorted keys, no
insignificant whitespace, no floats anywhere, exact, documented escaping rules) is the byte-level
contract every content hash and identity in the system is computed over. ONIX's own identity
ladder (config_hash, bar_fingerprint, signal_key, event_id, run_id, result_hash, and
others) is all built from the same SHA-256, domain-separated, length-prefixed primitive.
The schema set¶
At the pinned functional source commit (f80bc316ca01e9ea68a77ad6fd2ca0efe89ee7ba), the generated
contract manifest names 58 schemas, with a schema-set digest of
28fdebfb5b5a318455dacdff4375deb77237dc5a1d56ab26238cd27f59c2ec42 — the SHA-256 over the
concatenation of every schemas/*.schema.json file in filename order, as committed at that
commit. A consumer pins the contract by recording this digest (or the per-schema
schema_id/schema_version pairs) rather than by trusting a live endpoint's current shape at
integration time; every schema publishes its own schema_id and schema_version as a JSON Schema
const, so a supported-version registry is built by reading the schemas themselves, never
hand-maintained separately.
Categories, by schema count at this pin:
| Category | Representative schemas |
|---|---|
| Market data | bar_envelope, quote_tick, trade_tick, series_coverage, instrument_ref |
| Screener | feature_spec, feature_row, feature_row_delta, feature_state, screener_row, screener_snapshot, screener_health, screen_definition, screen_result, pattern_observation, projection_frame |
| Strategy authoring | strategy_template, strategy_summary, strategy_project, strategy_file, strategy_file_put_request, strategy_revision, strategy_revision_save_request, strategy_mutation_conflict, validation_receipt, strategy_authoring_registry |
| Backtesting & jobs | backtest_job_summary, backtest_job_detail, backtest_job_event, backtest_run_result, sandbox_start_request, sandbox_status |
| Execution reporting | order_summary, fill_summary, position_summary, account_state_summary, execution_report_page, execution_config |
| Signals & charts | signal_event, signal_retirement, chart_marker |
| Runtime & registries | engine_status, engine_command, run_receipt, capability_registry, condition_registry, integration_capability |
| Optimization | optuna_study, optuna_trial |
| IBKR-specific | ibkr.cancel_command, ibkr.command_result, ibkr.connection_state, ibkr.instrument_ref_additions, ibkr.order_command, ibkr.search_query, ibkr.search_result, ibkr.selection_row, ibkr.trading_session |
A small number of schemas have been through a versioned revision at this pin —
backtest_job_detail (v2), fill_summary (v2), order_summary (v2), position_summary (v2),
run_receipt (v2), strategy_revision (v2), strategy_revision_save_request (v2), and
validation_receipt (v2) — each bump additive and documented, never a silent reshape of an
existing version.
Discovering operations: the capability registry¶
Rather than requiring a consumer to diff route tables by hand, the backend publishes a single
derived document, onix.capability_registry, at GET /v2/registry. It is generated, never
hand-authored, directly from the real gateway_v2 route tables and the real MCP tool table, and a
test walks both live tables to fail loudly if the registry ever drifts from what is actually
dispatched. Each operation entry states its stable dotted id, wire version, effect kind
(QUERY/COMMAND/STREAM — the operation's effect, not its HTTP verb: a bounded POST query is
still QUERY), HTTP method/path, the one MCP tool that fronts it (when exactly one does),
participating schema ids, provider gating, and whether it mutates real venue order/execution state
(requires_paper, requires_confirmation).
GET /v2/registry wraps the static registry with a live availability overlay per operation,
using a fixed vocabulary: READY, UNSUPPORTED (the node has no backing method, or explicitly
declares it unsupported), WARMING, DISABLED, UNAVAILABLE (the node has the seam but
deliberately does not serve it this release), UNKNOWN (multi-venue aggregation only, when an
upstream could not be reached), and UNPUBLISHED (reserved for a future entry declared ahead of
its implementation — never produced by this build's derive-from-real-routes approach). Availability
is resolved per node, not once globally — the same operation id can be READY on one node and
UNAVAILABLE/UNSUPPORTED on another (see trading/portfolio-risk.md
for the concrete account/portfolio/order/fill/position example). A static declaration and a live
health signal are treated as different claims with different staleness on purpose, rather than
regenerating the whole document on every request.
Each OperationDescriptor additionally carries a providers field — empty means provider-neutral
(any node serves it), a non-empty list (["ibkr"] today) names the operation's gate — and
requires_paper/requires_confirmation flags that are true only for the two operations with a
real, consequential external side effect (POST /v2/orders, POST /v2/orders/cancel). This is the
backend's own, generated visibility/gating classification for every published operation; it is not
an authentication model (this backend publishes no session/identity layer of its own — see
nautilus-boundary.md and mcp.md for the surfaces that
exist instead).
REST and streaming surfaces, by area¶
The full route table is large; each area is documented on its own page rather than reproduced
here: data/catalog.md and data/aggregation.md for
bars/resolutions/hydration/coverage, trading/strategy-authoring.md
and trading/backtesting.md for the Strategy Studio and backtest
surfaces, trading/portfolio-risk.md for account/position/order
reads, and screener.md for the screener routes. Every list endpoint follows the
same cursor-pagination envelope; every streaming endpoint (GET /v2/stream/*) is
Server-Sent Events with a periodic heartbeat event, never a custom WebSocket protocol.
Evidence and source pins for this page
Verified. Current behaviour, confirmed in source at the pinned commit.
Verified on against the following immutable sources:
backend@efa38e04:docs/handoff/contract-manifest.jsonbackend@efa38e04:docs/contracts/market-spine-v2.mdbackend@efa38e04:docs/contracts/capability-registry-v1.mdbackend@efa38e04:docs/contracts/identity.md
Status tokens are defined on the documentation and status model page. Every pin on this site is listed under versions and source pins.