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+jsonwithtype,title,status,detail, andinstance. - 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)">"price"</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)">"0.72"</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"size_tokens"</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)">"order_count"</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.
| Access | Meaning |
|---|---|
| Open | No session or desk header |
| Session | Signed-in session; no desk header |
| Desk | Signed-in membership plus x-mm-account-id; each route below states any mutation rule |
| Active | OWNER or TRADER, active account, positive venue-set credit, and open venue, account, and instrument controls |
| Venue | Signed-in venue authority; no participant desk header |
| Intake | Submission 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
| Access | Method and route | Purpose |
|---|---|---|
| Open | POST /auth/register | Create a user; does not create a session |
| Open | POST /auth/login | Create a browser session |
| Session | POST /auth/logout | End the current session |
| Session | GET /auth/me | Read the user and desk memberships |
| Session | GET /accounts | List available desks |
| Session | POST /accounts | Register a disabled, zero-credit BUYER, SELLER, or BROKER desk |
| Intake | POST /onboarding | Submit onboarding details |
| Intake | POST /contact | Submit contact details where contact intake is enabled |
Catalogue, prices, and clock
| Access | Method and route | Purpose |
|---|---|---|
| Open | GET /models | Page the model catalogue |
| Open | GET /models/{slug} | Read model detail and provider matrix |
| Open | GET /models/{slug}/price-history | Read endpoint observation points, capped at 5,000 |
| Open | GET /providers | Page providers |
| Open | GET /providers/{slug} | Read provider detail |
| Open | GET /ingest/status | Read catalogue freshness |
| Open | GET /clock | Read timestamp quality and current session |
| Open | GET /launch | Read durable trading availability |
| Open | GET /instruments | Filter and page instruments |
| Open | GET /market/prices | Read a bounded market-price snapshot |
| Open | GET /market/prices/{symbol}/legs | Read leg contributions for one symbol |
| Open | GET /instruments/{symbol}/book | Read up to 200 levels per side |
| Open | GET /instruments/{symbol}/trades | Read up to 500 recent trades |
| Open | GET /market/replay | Recover bounded public executions by cursor |
| Open | GET /curve | Read 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
| Access | Method and route | Purpose |
|---|---|---|
| Open | GET /benchmarks | Read public benchmark methodology identities |
| Open | GET /benchmarks/{code}/publications | Read 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
| Access | Method and route | Purpose |
|---|---|---|
| Session | GET /external-markets | Read supported venue capability statuses |
| Session | GET /external-markets/{venue}/products | Read an attributed external catalogue |
| Session | GET /external-markets/{venue}/products/{product_code}/snapshot | Read 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
| Access | Method and route | Purpose |
|---|---|---|
| Open | GET /bundles | Page listed bundle instruments |
| Open | POST /bundles/quote | Price a proposed bundle composition |
| Active | POST /bundles | Submit a priceable Spot bundle for a venue decision |
| Open | POST /calculator/quote | Compare 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
| Access | Method and route | Purpose |
|---|---|---|
| Desk | GET /orders | Page the desk's orders |
| Active | POST /orders | Submit an order |
| Desk | GET /orders/outcome | Recover one account-scoped durable outcome |
| Desk | GET /orders/replay | Recover the desk's private executions by cursor |
| Desk | POST /orders/preview | Preview notional and fee projections |
| Desk | PATCH /orders/{id}/cancel | Cancel the desk's order |
| Desk | GET /positions | Page desk positions |
| Desk | GET /fills | Page desk fills |
| Desk | GET /fees/schedule | Read the desk's current rate card |
| Desk | GET /statements | Read 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
| Access | Method and route | Purpose |
|---|---|---|
| Desk | GET /capacity/listings | Page the selected desk's capacity products |
| Active | POST /capacity/listings | Submit Seller capacity for a venue decision |
| Desk | PATCH /capacity/listings/{id} | Deactivate or reduce an owned listing |
| Desk | GET /forward-offers | Page the selected provider's curve points |
| Active | POST /forward-offers | Publish a fixed-window provider curve point |
| Desk | PATCH /forward-offers/{id} | Amend, pause, or resume an owned curve point |
| Open | GET /rfqs | Page RFQs |
| Open | GET /rfqs/{id} | Read RFQ detail and quotes |
| Active | POST /rfqs | Create an RFQ |
| Active | POST /rfqs/{id}/quotes | Submit a quote |
| Active | POST /quotes/{id}/accept | Accept 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
| Access | Method and route | Purpose |
|---|---|---|
| Venue | GET /operator/product-approvals | Page attributed product requests |
| Venue | GET /operator/product-approvals/{id} | Read one attributed product request |
| Venue | POST /operator/product-approvals/{id} | Record an APPROVE or REJECT decision |
| Venue | GET /operator/accounts | Page desks for authority review |
| Venue | GET /operator/accounts/{id} | Read one desk for authority review |
| Venue | POST /operator/accounts/{id}/authority | Record a desk trading-state or credit action |
| Venue | GET /operator/account-authority-actions | Page attributed desk-authority actions |
| Venue | GET /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
| Access | Method and route | Purpose |
|---|---|---|
| Desk | GET /capacity/contracts | List contracts visible to the selected buyer/provider desk |
| Desk | GET /capacity/contracts/{id} | Read one visible fixed-window contract |
| Desk | GET /capacity/contracts/{id}/usage | Read buyer-private four-leg usage |
| Desk | POST /capacity/contracts/{id}/usage | Record buyer usage within window and entitlement |
| Desk | GET /capacity/contracts/{id}/fulfillments | Read the provider's final self-attested report |
| Desk | POST /capacity/contracts/{id}/fulfillments | Record the provider's final self-attested report |
| Desk | GET /capacity/contracts/{id}/reconciliation | Read 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
| Access | Method and route | Purpose |
|---|---|---|
| Open | GET /signals | Page source items and classifications |
| Open | GET /signals/demand-index | Read demand-index buckets |
| Open | GET /signals/sources | Page public sources |
| Open | POST /calculator/quote | Quote a workload comparison |
Voice and autonomy
| Access | Method and route | Purpose |
|---|---|---|
| Desk | GET /voice/ice-servers | Read media relay configuration |
| Desk | GET /voice/autonomy | Read the desk policy |
| Desk | PUT /voice/autonomy | Write human-confirm or bounded autonomous policy |
| Desk | GET /voice/sessions | Page voice sessions |
| Desk | POST /voice/sessions | Create a session |
| Desk | GET /voice/sessions/{id} | Read session detail |
| Desk | POST /voice/sessions/{id}/transcript | Append a transcript segment |
| Desk | POST /voice/sessions/{id}/signal | Relay a media-negotiation message |
| Desk | POST /voice/sessions/{id}/confirm | Restate and confirm proposed terms |
| Desk | POST /voice/sessions/{id}/end | End 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
| Access | Method and route | Purpose |
|---|---|---|
| Desk | GET /algos | Page existing parent instructions |
| Desk | POST /algos | Create a bounded parent instruction |
| Desk | PATCH /algos/{id} | Pause, resume or cancel an existing record |
| Desk | GET /algos/{id}/children | Page 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
| Access | Method and route | Purpose |
|---|---|---|
| Desk | GET /price-brackets | Page the selected desk's price ladders |
| Desk | GET /price-brackets/{id} | Read one owned ladder and its venue counters |
| Active | POST /price-brackets | Create an atomic ladder aggregate |
| Desk | PATCH /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)">"items"</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)">"next_cursor"</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)">"total"</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/pricesis a bounded snapshot.limitdefaults to 500 and is clamped to 1–2,000;next_cursoris 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_truncatedwhen 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
totalfrom 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:
| Channel | Data frames |
|---|---|
book:{symbol} | BOOK_SNAPSHOT, BOOK_DELTA |
tape:{symbol}, tape:* | TRADE |
signals | SIGNAL |
index | DEMAND_INDEX |
venue | INGEST_STATUS, CLOCK_HEALTH |
instruments | INSTRUMENT_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)">"channel"</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)">"book:MODEL.BUNDLE.SPOT"</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)">"seq"</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)">"t"</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)">"2026-08-20T12:00:00Z"</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)">"type"</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)">"BOOK_DELTA"</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)">"data"</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.