DEV · local workspace

API surface

REST routes below are relative to /api/v1. Realtime uses /ws/v1/stream. This page documents the participant, public-data, and mounted venue-authority API; other operational and administrator endpoints are not part of this public map.

Ground rules

  • RFC 3339 UTC strings carry timestamps.
  • API errors use application/problem+json with type, title, status, detail, and instance.
  • Exact decimals—prices, monetary amounts, rates, ratios, percentages, MFT quantities, latency, and throughput—are JSON strings.
  • Counts and whole-token quantities are JSON numbers.
  • Signal scores and weights, and the clock's parts-per-million diagnostics, are JSON numbers.
  • Missing optional values are null; known empty collections are [].

Orders, trades, and fills carry exactly one size field. Spot uses integer size_tokens and null size_mft. Forward uses positive decimal-string size_mft, with up to six fractional places, and null size_tokens.

Book levels are a separate shape:

<span><span style="color: var(--shiki-color-text)">{ </span><span style="color: var(--shiki-token-keyword)">&quot;price&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;0.72&quot;</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">&quot;size_tokens&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">3000000</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">&quot;order_count&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">2</span><span style="color: var(--shiki-color-text)"> }</span></span>
<span></span>

Authentication and desks

Sign-in establishes a browser session. Registration creates the user but does not sign it in.

POST /auth/logout, GET /auth/me, and GET|POST /accounts require the session but no desk header. A desk-scoped request requires both the session and x-mm-account-id, using an account_id returned by /auth/me or the id returned by /accounts.

No session returns 401. A missing or malformed desk header returns 400. A desk unavailable to the signed-in user returns 404.

AccessMeaning
OpenNo session or desk header
SessionSigned-in session; no desk header
DeskSigned-in membership plus x-mm-account-id; each route below states any mutation rule
ActiveOWNER or TRADER, active account, positive venue-set credit, and open venue, account, and instrument controls
VenueSigned-in venue authority; no participant desk header
IntakeSubmission route whose availability can depend on deployment intake settings

Trading and product authority

POST /accounts registers a desk with trading_state: "TRADING_DISABLED", credit_limit_usd: "0", and an OWNER membership for its creator. Supplying a positive credit_limit_usd returns 403 credit-approval-required; the participant account route cannot grant credit or change the desk's trading state.

An exposure-opening mutation requires an OWNER or TRADER membership, an ACTIVE account with positive credit set by the venue, and open venue and account controls. A request tied to an instrument also requires that instrument's control to be open. The stable refusals are 403 trading-authority-required, 409 account-trading-unavailable, and 409 trading-control-active; creating capacity additionally requires a SELLER desk or returns 403 capacity-issuer-required.

Cancellation, capacity deactivation or reduction, algo pause or cancel, and fixed-window evidence writes remain available to an eligible OWNER or TRADER when controls prevent new exposure. Those paths retain their resource and lifecycle validation.

Capacity and Spot bundle submissions are product requests, not immediate listings. Each body requires a participant reason and can carry an idempotency_key. A first valid request records the product as inactive and returns 409 product-approval-required with approval_request_id; an exact pending replay returns the same request. An approved replay returns the normal resource. A Forward bundle submission returns 409 forward-listing-unavailable.

Route map

Identity and intake

AccessMethod and routePurpose
OpenPOST /auth/registerCreate a user; does not create a session
OpenPOST /auth/loginCreate a browser session
SessionPOST /auth/logoutEnd the current session
SessionGET /auth/meRead the user and desk memberships
SessionGET /accountsList available desks
SessionPOST /accountsRegister a disabled, zero-credit BUYER, SELLER, or BROKER desk
IntakePOST /onboardingSubmit onboarding details
IntakePOST /contactSubmit contact details where contact intake is enabled

Catalogue, prices, and clock

AccessMethod and routePurpose
OpenGET /modelsPage the model catalogue
OpenGET /models/{slug}Read model detail and provider matrix
OpenGET /models/{slug}/price-historyRead endpoint observation points, capped at 5,000
OpenGET /providersPage providers
OpenGET /providers/{slug}Read provider detail
OpenGET /ingest/statusRead catalogue freshness
OpenGET /clockRead timestamp quality and current session
OpenGET /launchRead durable trading availability
OpenGET /instrumentsFilter and page instruments
OpenGET /market/pricesRead a bounded market-price snapshot
OpenGET /market/prices/{symbol}/legsRead leg contributions for one symbol
OpenGET /instruments/{symbol}/bookRead up to 200 levels per side
OpenGET /instruments/{symbol}/tradesRead up to 500 recent trades
OpenGET /market/replayRecover bounded public executions by cursor
OpenGET /curveRead spot and tenor points

Price-history observations carry time, Prompt, Output, and optional latency, throughput, and uptime values. They are endpoint observations rather than OHLC candles.

GET /market/replay is the durable public-tape recovery path. It accepts an optional cursor and a bounded limit from 1 through 256 (default 100), and returns execution price, symbol, trade identity, unit-appropriate size, instrument sequence, event ordinal, occurrence time, next_cursor, has_more, and retained oldest/newest event identifiers. The projection omits account, order, and command identities. A cursor before the retained floor returns a typed 400; refresh the market snapshot or reconcile before resuming the live stream.

GET /launch is the open, no-desk read for the durable trading-availability interlock. It returns state (LOCKED or OPEN), an authorization identity only when open, and bounded evidence and approval counts. Only OPEN admits new exposure; reference-data availability is a separate state. An unavailable or malformed status must never be treated as open.

Public benchmark artifacts

AccessMethod and routePurpose
OpenGET /benchmarksRead public benchmark methodology identities
OpenGET /benchmarks/{code}/publicationsRead explicitly promoted public artifacts

/benchmarks exposes only methodologies marked PUBLIC with an append-only, attributed methodology promotion and can return an empty page. Before response, each stored definition is reconstructed through the typed methodology rules; its code, version, effective time, and checksum must match its stored identity. A publication item is returned only when its methodology is public, the artifact has an explicit public promotion, and its canonical payload matches its checksum. A valid methodology can have no promoted artifacts.

Both benchmark endpoints default to limit=1 and reject every other limit with 400. This one-item response bound applies because an individual methodology definition or publication artifact can be as large as 16 MiB.

External reference markets

AccessMethod and routePurpose
SessionGET /external-marketsRead supported venue capability statuses
SessionGET /external-markets/{venue}/productsRead an attributed external catalogue
SessionGET /external-markets/{venue}/products/{product_code}/snapshotRead one attributed price snapshot

These routes require a session but no desk header. Responses for CME, ICE, NODAL, and CBOE carry the provider capability, product identity, freshness and source-attribution fields used by reference panels.

Bundles and calculator

AccessMethod and routePurpose
OpenGET /bundlesPage listed bundle instruments
OpenPOST /bundles/quotePrice a proposed bundle composition
ActivePOST /bundlesSubmit a priceable Spot bundle for a venue decision
OpenPOST /calculator/quoteCompare workload cost and compatible terms

A quote can return a null price and an availability reason when no eligible endpoint prices every included leg.

Orders, fees, and positions

AccessMethod and routePurpose
DeskGET /ordersPage the desk's orders
ActivePOST /ordersSubmit an order
DeskGET /orders/outcomeRecover one account-scoped durable outcome
DeskGET /orders/replayRecover the desk's private executions by cursor
DeskPOST /orders/previewPreview notional and fee projections
DeskPATCH /orders/{id}/cancelCancel the desk's order
DeskGET /positionsPage desk positions
DeskGET /fillsPage desk fills
DeskGET /fees/scheduleRead the desk's current rate card
DeskGET /statementsRead a period statement

The order body supplies MARKET, LIMIT, STOP, STOP_LIMIT, or PEG; GTC, DAY, IOC, or FOK; and exactly one instrument-appropriate size. See Orders and matching.

Ordinary direct REST and FIX placement requires a non-empty account-scoped client_order_id; FIX carries the same identity as ClOrdID. Voice placement may omit it because the gateway derives a stable voice:{session_id} identity before admission. Reusing an identity that already names a durable order returns 409 client-order-id-conflict with existing_order_id. Reconcile that order or its command outcome before choosing a new identity. An unchanged retry can return the original committed result; a pending or ambiguous result is reconciled through GET /orders/outcome. Another account can use the same text independently.

GET /orders/outcome requires at least one of client_order_id, order_id, or command_id and is scoped to the selected desk. It returns the durable order and/or command outcome, refuses conflicting selectors with 409, and returns 404 when no matching account outcome exists. It never retries or places an order.

GET /orders/replay requires the selected desk and accepts an optional cursor and a bounded limit from 1 through 256 (default 100). It scans the durable execution stream while advancing over other accounts, returns only executions involving the selected desk, and includes next_cursor, has_more, and the retained oldest/newest event identifiers. A cursor before retention returns a typed 400; do not treat a partial history as a complete private record.

Capacity and negotiated flow

AccessMethod and routePurpose
DeskGET /capacity/listingsPage the selected desk's capacity products
ActivePOST /capacity/listingsSubmit Seller capacity for a venue decision
DeskPATCH /capacity/listings/{id}Deactivate or reduce an owned listing
DeskGET /forward-offersPage the selected provider's curve points
ActivePOST /forward-offersPublish a fixed-window provider curve point
DeskPATCH /forward-offers/{id}Amend, pause, or resume an owned curve point
OpenGET /rfqsPage RFQs
OpenGET /rfqs/{id}Read RFQ detail and quotes
ActivePOST /rfqsCreate an RFQ
ActivePOST /rfqs/{id}/quotesSubmit a quote
ActivePOST /quotes/{id}/acceptAccept a quote

Activation, expansion, and repricing are not accepted by the capacity update route. A capacity or Spot bundle remains inactive while its venue decision is pending.

GET /capacity/listings requires membership in the selected desk and returns only that desk's rows. It retains the model_slug and active filters and the standard cursor-page shape; total is null. Each current row carries approval_request_id and approval_state (PENDING, APPROVED, or REJECTED). Both fields are null only for a legacy row without a product request.

Forward offers are private to the selected Seller desk. Publication requires an approved active provider listing and a matching active, non-halted, fixed-window BLENDED FORWARD product. active:false is risk-reducing and remains available when exposure admission is closed; amendments that keep a point active and reactivation require Active access. See Spot and forward instruments.

Venue authority

AccessMethod and routePurpose
VenueGET /operator/product-approvalsPage attributed product requests
VenueGET /operator/product-approvals/{id}Read one attributed product request
VenuePOST /operator/product-approvals/{id}Record an APPROVE or REJECT decision
VenueGET /operator/accountsPage desks for authority review
VenueGET /operator/accounts/{id}Read one desk for authority review
VenuePOST /operator/accounts/{id}/authorityRecord a desk trading-state or credit action
VenueGET /operator/account-authority-actionsPage attributed desk-authority actions
VenueGET /operator/account-authority-actions/{id}Read one attributed desk-authority action

Product decisions require decision, reason, and idempotency_key. Desk-authority actions require at least one of trading_state or credit_limit_usd, plus reason and idempotency_key. Exact replays return the recorded action; changing an action or decision under the same key returns 409 approval-idempotency-conflict. A participant session without venue authority returns 403 venue-operator-required, and a requester cannot decide its own product request.

An authority-review account item carries id, code, display_name, role, organisation, exact-string credit_limit_usd, trading_state, created_at, and is_demo. Each product-approval item carries an immutable product snapshot from request time. Capacity snapshots include kind, model and provider slugs, region, token rate, floor price, service tier, latency ceiling, and throughput floor. Spot bundle snapshots include kind, symbol, model and provider slugs, service tier, basket_composition, quote unit, lot size, and tick size.

Fixed-window delivery evidence

AccessMethod and routePurpose
DeskGET /capacity/contractsList contracts visible to the selected buyer/provider desk
DeskGET /capacity/contracts/{id}Read one visible fixed-window contract
DeskGET /capacity/contracts/{id}/usageRead buyer-private four-leg usage
DeskPOST /capacity/contracts/{id}/usageRecord buyer usage within window and entitlement
DeskGET /capacity/contracts/{id}/fulfillmentsRead the provider's final self-attested report
DeskPOST /capacity/contracts/{id}/fulfillmentsRecord the provider's final self-attested report
DeskGET /capacity/contracts/{id}/reconciliationRead final quantity findings when present

These routes expose evidence for an existing fixed-window contract; new forward instruments remain HALTED, and the routes do not admit or match a forward order. Usage is buyer-private. Either contract party can read the provider report and final findings, while only the provider can submit its final self-attested report.

Usage and provider-report writes retain Prompt, Cache read, Cache write, and Output quantities. Negative leg quantities return 422 before any evidence is recorded. A first write returns 201; an exact replay returns 200; changing the evidence under the same request or report reference returns 409 idempotency-conflict. Reusing a provider report reference for a different contract returns the privacy-safe 409 report-reference-conflict. A report is provider-attested rather than independently verified.

Contract and buyer-private usage reads use the standard { items, next_cursor, total } cursor page with an exact total. The provider report and final findings are nullable until present. These records do not calculate penalties, move payments, transfer or resell a contract, or establish financial finality. See Forward delivery evidence.

Signals

AccessMethod and routePurpose
OpenGET /signalsPage source items and classifications
OpenGET /signals/demand-indexRead demand-index buckets
OpenGET /signals/sourcesPage public sources
OpenPOST /calculator/quoteQuote a workload comparison

Voice and autonomy

AccessMethod and routePurpose
DeskGET /voice/ice-serversRead media relay configuration
DeskGET /voice/autonomyRead the desk policy
DeskPUT /voice/autonomyWrite human-confirm or bounded autonomous policy
DeskGET /voice/sessionsPage voice sessions
DeskPOST /voice/sessionsCreate a session
DeskGET /voice/sessions/{id}Read session detail
DeskPOST /voice/sessions/{id}/transcriptAppend a transcript segment
DeskPOST /voice/sessions/{id}/signalRelay a media-negotiation message
DeskPOST /voice/sessions/{id}/confirmRestate and confirm proposed terms
DeskPOST /voice/sessions/{id}/endEnd a session

Human confirmation is the default. Read Voice autonomy before setting AUTONOMOUS.

Switching into AUTONOMOUS is exposure-enabling and therefore requires Active access. Switching back to HUMAN_CONFIRM remains available with Desk access.

Execution algos

AccessMethod and routePurpose
DeskGET /algosPage existing parent instructions
DeskPOST /algosCreate a bounded parent instruction
DeskPATCH /algos/{id}Pause, resume or cancel an existing record
DeskGET /algos/{id}/childrenPage existing child-order history

A valid POST /algos request returns the parent identity and initial lifecycle state. The resume action checks the same account, instrument and execution limits before moving a paused record back to RUNNING. List, child-history, pause and cancel operations remain available subject to desk scope and lifecycle-state validation.

Price ladders

AccessMethod and routePurpose
DeskGET /price-bracketsPage the selected desk's price ladders
DeskGET /price-brackets/{id}Read one owned ladder and its venue counters
ActivePOST /price-bracketsCreate an atomic ladder aggregate
DeskPATCH /price-brackets/{id}Activate or deactivate an owned ladder

Creation requires an Idempotency-Key header (1–128 bytes, no control characters) and an Active desk. The body names an instrument, BUY or SELL, one through 64 unique tick-aligned levels, positive token sizes compatible with the instrument lot, a positive max_open_tokens, and an optional positive budget_usd. A one-sided ladder omits spread_bps; a two-sided ladder must supply it from 1 through 10,000. Repeating the same account-scoped key and intent returns the existing ladder; changing the intent returns 409.

The response includes each level's price, size, filled quantity, active state and resting child order, plus aggregate open/filled quantities, budget, spend and active state. Venue fills and child-order attribution own those counters; callers cannot write them. Deactivation is risk-reducing but is refused while the ladder still owns a live child order. Activation rechecks the selected instrument and desk authority.

Paging and response shapes

Cursor-paged routes accept limit and cursor and return:

<span><span style="color: var(--shiki-color-text)">{ </span><span style="color: var(--shiki-token-keyword)">&quot;items&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> []</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">&quot;next_cursor&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">null</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">&quot;total&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">null</span><span style="color: var(--shiki-color-text)"> }</span></span>
<span></span>

The default page size is 50 and the maximum is 200. next_cursor is null on the last page; total is exact when available and otherwise null. Cursor paging applies to models, providers, accounts, instruments, orders, positions, fills, bundles, capacity listings, forward offers, RFQs, capacity contracts, buyer-private usage records, voice sessions, algos, algo children, signals, signal sources, product approvals, authority-review accounts, and desk-authority actions.

Exceptions:

  • /market/prices is a bounded snapshot. limit defaults to 500 and is clamped to 1–2,000; next_cursor is always null.
  • Instrument trades return a bare array, newest first, with a default and maximum of 500.
  • Price history returns endpoint observations capped at 5,000.
  • Statements report lines_truncated when their 1,000 trade-line itemization ceiling is reached.
  • Both benchmark endpoints use the cursor-page envelope, default to one item, and accept only limit=1.
  • External-market status, catalogue, and snapshot responses are bounded read models rather than cursor pages.
  • Capacity contract and buyer-private usage pages return an exact total; their provider-report and final-finding reads are nullable objects as documented above.
  • Product-approval, authority-review account, and desk-authority-action pages also return an exact total from the same repeatable read as their items.
  • Price-ladder pages use the standard bounded page envelope and are scoped to the selected desk; ladder detail and outcome responses are single objects.
  • Public and private execution replay use bounded cursor scans with retention metadata rather than the ordinary page envelope.

Realtime

The client operations are subscribe, unsubscribe, and ping. A request can name at most 64 channels.

Public channel and frame pairs are:

ChannelData frames
book:{symbol}BOOK_SNAPSHOT, BOOK_DELTA
tape:{symbol}, tape:*TRADE
signalsSIGNAL
indexDEMAND_INDEX
venueINGEST_STATUS, CLOCK_HEALTH
instrumentsINSTRUMENT_LISTED

Control frames are SUBSCRIBED, UNSUBSCRIBED, PONG, and ERROR. Every server frame has:

<span><span style="color: var(--shiki-color-text)">{</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-keyword)">&quot;channel&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;book:MODEL.BUNDLE.SPOT&quot;</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-keyword)">&quot;seq&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">42</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-keyword)">&quot;t&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;2026-08-20T12:00:00Z&quot;</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-keyword)">&quot;type&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;BOOK_DELTA&quot;</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-keyword)">&quot;data&quot;</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> {}</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>

Sequence numbers are monotonic per channel. When a client detects a gap, refresh the corresponding REST snapshot before applying more deltas.