Skip to content

Gateway contract and schema surface

VerifiedOwner Backend / platformLast verified backend@efa38e04e2db37a444e9f17100323c2ad4b83647 nautilus@2.0.0rc3

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_cursornull 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.json
  • backend@efa38e04:docs/contracts/market-spine-v2.md
  • backend@efa38e04:docs/contracts/capability-registry-v1.md
  • backend@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.