YM Predictions Controlled pilot Download OpenAPI 3.1

YM Trading API v2 Pilot

Status: controlled pilot
Last reviewed: 2026-09-02

This package describes the external interface currently available to approved YM market-making and API-trading participants. It is participant-facing documentation, not an architecture plan and not a service-level agreement.

Contract activation is environment-specific. Do not submit v2 commands until YM confirms that v2 is active for the supplied endpoint and account.

YM uses DXmatch as the matching and venue-order authority. Clients authenticate to YM and use YM APIs; direct DXmatch credentials are not part of the pilot. YM remains responsible for participant identity, admission, collateral, idempotency, market-generation fencing, account projections, ledger posting, market lifecycle and settlement.

Availability language

Label Meaning
Available Implemented and enabled for approved accounts.
Pilot Implemented and available to explicitly onboarded participants, but not yet covered by a public production SLA.
Preview Useful for evaluation, but its recovery or capacity contract is not suitable for production market making.
In development Planned or being built; clients must not depend on it.
Not offered Deliberately outside the current external contract.

Current pilot surface

Capability Status
Canonical event, family and market discovery Available
Public L2 book snapshots, recent trades and market statistics Available
OAuth 2.0 client-credentials authentication Pilot onboarding
Canonical REST NEW, REPLACE and CANCEL Pilot
Batch NEW and batch CANCEL In development; excluded from the v2 pilot until per-item replay conformance passes
Canonical order, position, portfolio and balance reads Pilot
Participant trade-history read Pilot; legacy YES-book coordinate, not private-feed recovery authority
Resumable private order and execution WebSocket feed Pilot
Consumer market-data WebSocket Preview; not a professional recovery contract
Persistent WebSocket order entry In development
Professional recoverable streaming market data In development
FIX order entry or drop copy In development; not part of this pilot
Mass cancel, cancel-on-disconnect and participant kill switch In development
External mass-quote or quote-set replacement Not offered in this pilot

Documents

  1. Quickstart
  2. OpenAPI guide and curated OpenAPI
  3. Authentication and scopes
  4. Markets, identity and lifecycle
  5. Order entry and lifecycle
  6. Private trading feed
  7. Errors and retry policy
  8. Market data
  9. Limits, availability and roadmap

Contract boundaries

v2 transition

The public URL namespace remains /v1; schema_version: 2 versions the order and private-feed payload contract. v2 replaces the former three-axis order input with one consumer-facing model: action, outcome, and the selected outcome's price_cents. The retired public fields are side, position_side, intent, and decimal price. They are not compatibility aliases and v2 rejects them.

REST order resources and private-feed fills use the same selected-outcome price coordinate. Private-feed messages carry schema_version: 2; a v1 cursor cannot resume v2. Before cutover, consumers must durably finish their v1 stream through the announced boundary. A cursorless v2 connection then replaces nonterminal order state only; it does not replay v1 terminal orders or fill history. Internal matching, collateral, ledger, and settlement semantics are unchanged. The public L2 book and public trade tape remain YES-book market data. The current authenticated /v1/trades history also exposes venue side and YES-book price; use the v2 private feed for live participant-relative fill truth.

Forward path

The REST contract and private feed are suitable for a controlled integration now. Before general professional availability, YM intends to add persistent WebSocket command entry, a professional recoverable market-data transport, cancel-safety primitives, generalized firm/strategy onboarding, high- availability proof and published capacity/SLO terms. New transports will adapt the same canonical command and event model rather than create separate trading logic.

Sources of truth

For the pilot, use this order when documents appear to disagree:

  1. The current curated OpenAPI in this directory.
  2. Runtime behavior confirmed in the participant UAT environment.
  3. This explanatory documentation.
  4. Roadmap notes marked In development.

Report contract discrepancies to the YM integration contact supplied during onboarding. Include the response status, machine-readable error code, UTC time, request correlation ID and client request ID. Never send client secrets or bearer tokens.

1. Quickstart

Status: controlled pilot

This guide uses the v2 order contract. Confirm v2 activation for the target environment before sending commands; v1 fields are intentionally rejected.

This sequence opens the private feed before submitting an order, then follows one order through NEW, REPLACE and CANCEL. Use an account and market explicitly approved for UAT. Do not run the example against an unapproved financial environment.

Prerequisites

YM supplies each approved integration with:

The initial pilot binds one confidential client to one financial account. Do not place a user_id in an order request.

Set local variables without committing their values:

export YM_BASE_URL="https://ympredictions.com"
export YM_TOKEN_URL="https://auth.ympredictions.com/realms/ymp/protocol/openid-connect/token"
export YM_CLIENT_ID="supplied-by-ym"
export YM_CLIENT_SECRET="supplied-by-ym"
export YM_ACCOUNT_ID="supplied-by-ym"

1. Obtain a short-lived access token

TOKEN_RESPONSE="$(curl -sS -X POST "$YM_TOKEN_URL" \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'grant_type=client_credentials' \
  --data-urlencode "client_id=$YM_CLIENT_ID" \
  --data-urlencode "client_secret=$YM_CLIENT_SECRET")"

export YM_ACCESS_TOKEN="$(printf '%s' "$TOKEN_RESPONSE" | jq -r '.access_token')"

The current pilot token lifetime is five minutes. Request a new token before expiry; do not expect a refresh token from the client-credentials grant.

2. Select a canonical market

curl -sS \
  "$YM_BASE_URL/v1/markets?view=canonical&status=active&limit=20" \
  | jq '.markets[] | {
      market_id: .id,
      market_generation,
      status,
      publication_state,
      title
    }'

Select a leaf with all of the following:

The order API remains the final admission authority. A catalog result is not a reservation of future tradeability.

export YM_MARKET_ID="selected-immutable-market-id"
export YM_MARKET_GENERATION="selected-positive-generation"

3. Read the current L2 snapshot

curl -sS \
  "$YM_BASE_URL/v1/book?market_id=$YM_MARKET_ID&depth=20" \
  | jq .

The snapshot is public. seq describes the current YM projection; it is not a durable professional replay cursor. See Market data.

4. Open the private feed

Open this in a second terminal before sending the order:

npx wscat \
  -c 'wss://ympredictions.com/v1/trading-feed' \
  -H "Authorization: Bearer $YM_ACCESS_TOKEN"

Wait for this bootstrap sequence:

stream.welcome
stream.snapshot_started
stream.snapshot_chunk (zero or more)
stream.snapshot_completed
stream.ready

Only submit commands after stream.ready. Persist each event's signed cursor after the event has been validated and durably applied locally.

5. Submit a resting order

The example buys ten YES contracts at 45 cents using GTC:

export YM_CLIENT_ORDER_ID="quickstart-order-$(date +%s)"
export YM_NEW_REQUEST_ID="quickstart-new-$(date +%s)-$RANDOM"

NEW_RESPONSE="$(curl -sS -X POST "$YM_BASE_URL/v1/orders" \
  -H "Authorization: Bearer $YM_ACCESS_TOKEN" \
  -H 'Content-Type: application/json' \
  -H "Idempotency-Key: $YM_NEW_REQUEST_ID" \
  --data "{
    \"client_order_id\": \"$YM_CLIENT_ORDER_ID\",
    \"market_id\": \"$YM_MARKET_ID\",
    \"market_generation\": $YM_MARKET_GENERATION,
    \"action\": \"BUY\",
    \"outcome\": \"YES\",
    \"price_cents\": 45,
    \"quantity\": 10,
    \"time_in_force\": \"GTC\"
  }")"

printf '%s' "$NEW_RESPONSE" | jq .
export YM_ORDER_ID="$(printf '%s' "$NEW_RESPONSE" | jq -r '.order.id')"

201 Created means YM admitted the command and durably created a PENDING order. Wait for order.working on the private feed, or read the canonical order until execution_status is WORKING, before treating it as venue-effective.

For a NO order, keep the same coordinate end to end. A request with "action":"BUY", "outcome":"NO", and "price_cents":35 must return and stream BUY / NO / 35. Never send or expect the internal complementary YES-book representation.

6. Read the canonical order

curl -sS \
  "$YM_BASE_URL/v1/orders/$YM_ORDER_ID" \
  -H "Authorization: Bearer $YM_ACCESS_TOKEN" \
  | jq .

Record order_version. A replacement is fenced by the version it was based on.

7. Replace the working order

This changes the effective price of the order's immutable YES outcome to 44 cents while retaining the target total quantity of ten contracts:

ORDER_RESPONSE="$(curl -sS \
  "$YM_BASE_URL/v1/orders/$YM_ORDER_ID" \
  -H "Authorization: Bearer $YM_ACCESS_TOKEN")"
export YM_ORDER_VERSION="$(printf '%s' "$ORDER_RESPONSE" | jq -r '.order_version')"
export YM_REPLACE_REQUEST_ID="quickstart-replace-$(date +%s)-$RANDOM"

curl -sS -X POST \
  "$YM_BASE_URL/v1/orders/$YM_ORDER_ID/replace" \
  -H "Authorization: Bearer $YM_ACCESS_TOKEN" \
  -H 'Content-Type: application/json' \
  -H "Idempotency-Key: $YM_REPLACE_REQUEST_ID" \
  --data "{
    \"expected_order_version\": $YM_ORDER_VERSION,
    \"price_cents\": 44,
    \"total_quantity\": 10
  }" | jq .

202 Accepted means the replacement command was admitted. The prior venue-effective price and quantity remain authoritative until order.replaced arrives.

8. Cancel the order

Do not send a cancel while a replacement is still pending. Wait for order.replaced, then use a new idempotency key:

export YM_CANCEL_REQUEST_ID="quickstart-cancel-$(date +%s)-$RANDOM"

curl -sS -X POST \
  "$YM_BASE_URL/v1/orders/$YM_ORDER_ID/cancel" \
  -H "Authorization: Bearer $YM_ACCESS_TOKEN" \
  -H 'Content-Type: application/json' \
  -H "Idempotency-Key: $YM_CANCEL_REQUEST_ID" \
  --data '{}' | jq .

202 Accepted is not cancellation finality. Wait for order.cancelled or a canonical terminal snapshot before releasing local risk.

9. Resume after disconnect

Reconnect with the last cursor your application fully applied:

wss://ympredictions.com/v1/trading-feed?cursor=<URL-encoded-signed-cursor>

The server replays events after that cursor and sends stream.ready. Delivery is at least once; deduplicate using event_id and never derive sequence numbers from the cursor.

Forward path

REST is the pilot command transport. Persistent WebSocket order entry is in development and will use the same IDs, idempotency, market-generation fence and canonical lifecycle. Existing REST clients will not need a separate business model when that transport becomes available.

2. Curated OpenAPI

Status: available for pilot integration

The standalone openapi-market-maker.yaml contains only the endpoints intended for approved API-trading participants. It is derived from YM's authoritative platform OpenAPI rather than being a second handwritten contract.

Included surface

The curated specification includes:

Deliberately excluded

The participant specification does not expose:

The absence of a path from this specification means it is not part of the market-maker pilot, even if another YM application uses that path internally.

Tooling

The file is OpenAPI 3.1 and can be imported into current OpenAPI tooling. For example:

npx @redocly/cli lint openapi-market-maker.yaml

Client generation is optional. YM recommends first integrating directly with the JSON contract so retry, idempotency and asynchronous effective-state semantics remain explicit.

Versioning

The v2 cutover is intentionally breaking: old order fields and v1 private-feed cursors are not translated. A cursorless v2 snapshot replaces nonterminal state only; retain v1 terminal/fill history through the announced boundary. Confirm environment activation before sending v2 traffic.

Forward path

The current artifact is checked into the repository as a curated snapshot of the authoritative specification. Before a public developer portal is launched, YM intends to enforce allowlist generation and drift detection in CI, publish a rendered reference site, and attach an explicit changelog to each external contract release. Runtime route-contract tests already protect the underlying platform specification.

3. Authentication and scopes

Status: controlled pilot onboarding

Professional clients authenticate to YM with OAuth 2.0 client credentials. The bearer token identifies both the approved confidential client and, during the initial pilot, one dedicated YM financial account.

Direct DXmatch credentials, browser passwords, API keys in URLs and shared credentials across firms are not supported.

Token endpoint

POST https://auth.ympredictions.com/realms/ymp/protocol/openid-connect/token
Content-Type: application/x-www-form-urlencoded
curl -sS -X POST \
  'https://auth.ympredictions.com/realms/ymp/protocol/openid-connect/token' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'grant_type=client_credentials' \
  --data-urlencode 'client_id=<supplied-client-id>' \
  --data-urlencode 'client_secret=<supplied-client-secret>'

Use the returned token on REST requests:

Authorization: Bearer <access_token>

The same header authenticates a headless connection to wss://ympredictions.com/v1/trading-feed.

Pilot scopes

Scope Authority
orders:write Submit approved NEW, REPLACE and CANCEL commands. Batch commands remain outside the v2 pilot.
orders:read Read the authenticated participant's orders, trades, positions and portfolio.
trading-feed:read Connect to the authenticated participant's private lifecycle feed.
balances:read Read balances for the account bound to the token.
trading:professional Select the explicitly configured professional capacity policy; it grants no data or trading authority by itself.

Scopes are assigned by YM during onboarding. A client cannot elevate itself by placing additional values in the token request.

Identity and account binding

Token lifecycle

The current pilot access-token lifetime is five minutes. Treat that as an operational setting, not a permanent protocol guarantee.

Immediate credential revocation and rotation are handled through the pilot onboarding contact. A revoked token must not be retried indefinitely.

Browser and headless clients

The private feed accepts authenticated headless clients without a browser Origin header. Browser Origin protections remain active where applicable and are not weakened by professional access. The current consumer market-data WebSocket has a different browser-oriented policy and is not the professional market-data contract.

Forward path

General professional availability will add explicit firm, application, strategy and account entitlements; self-service rotation and revocation; connection/subscription policy; and an audited onboarding workflow. mTLS may be added if operational or regulatory requirements justify it, but is not a pilot requirement. Future WebSocket or FIX command sessions will resolve to the same YM principal and account authority.

4. Markets, identity and lifecycle

Status: canonical discovery available; dedicated professional lifecycle stream in development

Every trading command targets one immutable leaf market_id and the exact current market_generation. Titles, slugs, URLs and provider identifiers are presentation or discovery data and must not be used as trading identity.

Hierarchy

Resource Purpose
Event The real-world occurrence, fixture, election or question grouping.
Market family A coordinated proposition such as match winner, set winner or tournament winner.
Market leaf One binary outcome market. Public orders select YES or NO; YM normalizes both to the leaf's internal YES book.

A family may contain one or many leaves. membership_complete describes whether the canonical family membership is complete; it does not make the entire family one tradable instrument.

Canonical discovery

Always request the canonical view:

GET /v1/markets?view=canonical
GET /v1/markets/{marketID}?view=canonical
GET /v1/events
GET /v1/events/{eventID}
GET /v1/events/{eventID}/market-families
GET /v1/market-families?view=canonical
GET /v1/market-families/{familyID}?view=canonical

Canonical collection pagination uses the opaque next_cursor; offset pagination is unsupported. Treat cursors as opaque and scoped to the request shape that produced them.

Provider mappings are returned only through explicit canonical expansions. They are diagnostic metadata, not stable order-entry identifiers.

Trading eligibility indicators

Before submitting an order, require:

These are client-side preflight indicators. YM rechecks authoritative admission, lifecycle, participant and collateral state atomically during order entry. A market can stop accepting commands after it was discovered.

PUBLIC_BLOCKED may remain visible for discovery, live presentation or history while admission is disabled. It is not a tradable state.

Market generation

market_generation is an optimistic safety fence around the market's current admission definition. It prevents a command constructed against an older definition from entering a newer market state.

On 409 stale_market_generation:

  1. Stop sending commands with the old generation.
  2. Fetch GET /v1/markets/{marketID}?view=canonical.
  3. Re-evaluate status, publication, close time and the changed definition.
  4. Rebuild the command with the new positive generation.
  5. Use a new client request ID if the economic command changed. Reuse the old ID only to recover the exact original payload.

Never increment or infer a generation locally.

Lifecycle behavior

Do not assume the scheduled start of an event is necessarily its trading close or resolution time. Use the canonical market fields and effective lifecycle events.

Revision versus generation

revision tracks canonical presentation/catalog changes. market_generation is the trading admission fence. A client must not substitute one for the other.

Forward path

Catalog REST is authoritative for the pilot. YM intends to add a professional market-lifecycle stream carrying market identity, generation, admission and close/drain transitions so clients do not need frequent catalog polling. That stream will be wake-driven and recoverable; it will not create a second source of market truth.

5. Order entry and lifecycle

Status: canonical REST NEW, REPLACE and CANCEL available in the controlled pilot

YM exposes one canonical order model. REST admission, canonical reads and the private feed describe the same order and command identities. Future WebSocket or FIX adapters will enter this same business path rather than create separate order semantics.

Three distinct states

Never collapse these layers into one generic accepted state:

Layer Authority Meaning
Command admission YM The command was durably accepted or rejected by YM.
Exchange execution DXmatch evidence projected by YM The effective working, filled, replaced or terminal state.
Financial posting YM ledger The resulting hold, fill and settlement posting state.

An HTTP 201 or 202 is command admission, not venue finality.

Action, outcome and price semantics

The public contract always describes the participant's selected outcome. Clients send action, outcome, and that outcome's price_cents:

action outcome Meaning
BUY YES Increase YES exposure at the stated YES price.
SELL YES Reduce YES exposure at the stated YES price.
BUY NO Increase NO exposure at the stated NO price.
SELL NO Reduce NO exposure at the stated NO price.

YM derives the internal YES-book side and OPEN/CLOSE accounting effect. Do not complement NO prices: BUY NO at 35 means pay 35 cents for NO. Naked shorting is not exposed; a SELL must be covered by the named outcome position.

Prices are integer cents from 0 through 100; quantities are positive whole contracts. The public professional contract currently exposes limit orders only.

Time in force

Value Behavior
GTC Rest until filled, explicitly cancelled or removed by market lifecycle. Preferred for professional resting liquidity.
IOC Attempt immediate execution and cancel any unfilled remainder. It remains a limit order with price protection.
DAY Venue-supported session-scoped lifetime. Do not use it as a substitute for a long-lived prediction-market order.

GTD, FOK, market, stop and iceberg orders are not currently exposed.

NEW

POST /v1/orders
Authorization: Bearer <token>
Idempotency-Key: <participant-scoped-command-id>
Content-Type: application/json

Required body:

{
  "client_order_id": "strategy-a-000001",
  "market_id": "immutable-market-id",
  "market_generation": 7,
  "action": "BUY",
  "outcome": "YES",
  "price_cents": 45,
  "quantity": 100,
  "time_in_force": "GTC"
}

Do not send user_id. client_order_id is participant-defined, has a maximum length of 200 characters and must remain unique within the participant's retained order history.

Do not send the retired v1 fields side, position_side, intent, or decimal price. Unknown request fields fail closed.

Responses:

YM transactionally records the admitted command, order, collateral reservation and durable downstream work before responding. DXmatch execution remains asynchronous.

REPLACE

POST /v1/orders/{orderID}/replace
Idempotency-Key: <new-command-id>
{
  "expected_order_version": 4,
  "price_cents": 46,
  "total_quantity": 120
}

Rules:

DX applies an accepted REPLACE to one existing venue order as a single-order mutation. YM admission is not proof that it became effective. REPLACE does not atomically replace a bid/ask pair.

CANCEL

POST /v1/orders/{orderID}/cancel
Idempotency-Key: <new-command-id>
Content-Type: application/json

{}

Idempotency

All single-order mutations require Idempotency-Key:

Transport timeout is not evidence of failure. Recover by replaying the exact request or querying the resulting canonical order.

Clients must durably retain each outbound command payload under its client_request_id. A command result identifies admission/outcome and current order state; it is not a copy of the client's command-request journal. There is currently no general query-by-client-request-ID endpoint.

Batch commands — not enabled for the v2 pilot

POST /v1/orders/batch
POST /v1/orders/cancel-batch

The endpoints exist in the platform but are excluded from the approved v2 pilot until per-item idempotent-replay and error-envelope conformance passes. Do not build a pilot strategy against them yet.

The intended contract accepts at most 250 items. Each item carries its own client_request_id and returns its own status, acceptance and retryability.

A batch is a transport convenience, not one atomic multi-order transaction. Clients must inspect every item and retry only the exact uncertain items with the same item IDs and payloads.

Canonical reads

GET /v1/orders/{orderID}
GET /v1/orders?market_id=...&execution_status=...&cursor=...&limit=...

Order reads expose:

The single-order response supplies an ETag derived from order_version and accepts If-None-Match.

If state_quality=RECONCILIATION_REQUIRED, stop mutating that order until YM has restored confirmed venue truth.

Canonical REST command and list envelopes carry schema_version: 2. The single-order GET returns the bare v2 Order resource; its URL remains /v1 and it does not add a second schema envelope.

Account projections

GET /v1/trades
GET /v1/positions
GET /v1/portfolio
GET /v1/accounts/{selfAccountID}/balances

These routes are self-scoped by the bearer token. Private fill events currently report financial settlement_status=POSTED; a fill is not presented as financially complete before its approved posting path succeeds.

GET /v1/trades is a legacy account-activity projection outside Order Contract v2: side and price_cents are in the YES-book venue coordinate, not the selected-outcome v2 order coordinate. It is useful for reconciliation but is not the live v2 recovery authority. Use private-feed order.fill, whose nested order and fill price are participant- relative, for live strategy state. The legacy endpoint is deliberately omitted from the curated v2 OpenAPI.

Forward path

Persistent WebSocket order entry, post-only/maker-or-cancel, mass cancellation, cancel-on-disconnect and participant kill controls are in development. External mass quote is not part of the current contract. These additions will reuse the same command IDs, idempotency, order versions, collateral rules and private events.

6. Private trading feed

Status: controlled pilot

Current message schema: v2

Endpoint:

wss://ympredictions.com/v1/trading-feed

Required scope: trading-feed:read

The feed is participant-scoped and read-only. It reports canonical command, order, replacement, fill and terminal state regardless of whether the change originated from REST, lifecycle control or another authorized session for the same account.

Connection

Pass the access token in the WebSocket upgrade request:

Authorization: Bearer <access_token>

Participant identity is derived from the token. No user_id, account, MPID or venue-session selector is accepted.

WebSocket compression is disabled for the low-latency pilot profile. Clients must accept JSON text frames up to the max_frame_bytes announced in stream.welcome.

New session bootstrap

Without a cursor, the feed sends:

  1. stream.welcome
  2. stream.snapshot_started
  3. zero or more stream.snapshot_chunk frames
  4. stream.snapshot_completed
  5. events committed after the snapshot high-water mark
  6. stream.ready
  7. live lifecycle events and stream.heartbeat

The snapshot contains all canonical nonterminal orders for the authenticated participant. Replace local nonterminal state with the completed snapshot, then apply replayed events in order. Do not begin strategy command flow before stream.ready.

stream.welcome advertises the contract name, heartbeat interval, maximum frame size and at_least_once delivery mode. Use those values rather than hardcoding deployment defaults.

For v2 the advertised contract is Private Order & Execution Feed v2, and every lifecycle and control message carries schema_version: 2.

Resume

Each lifecycle event includes an opaque signed cursor. Persist it only after the event has been validated and durably applied locally.

Reconnect with:

wss://ympredictions.com/v1/trading-feed?cursor=<URL-encoded-last-applied-cursor>

The server replays events after the supplied cursor, then sends stream.ready. A resume session does not send another account snapshot unless the client reconnects without a cursor.

The cursor is:

A cursor issued by v1 is invalid for v2. Before cutover, durably consume v1 through the announced boundary and retain terminal/fill history. Then discard the v1 cursor and connect without a cursor. The v2 snapshot replaces only nonterminal order state; it does not replay v1 terminal orders or fill history.

Delivery and convergence

Delivery is at least once. A correct consumer must:

  1. Require schema_version == 2 and the expected account scope.
  2. Deduplicate lifecycle facts by event_id.
  3. Apply an order snapshot only when its order_version is newer than the locally stored version.
  4. Persist the event and its cursor atomically in the client's own store.
  5. Keep independent orders independent; do not assume one global exchange ordering across markets.

Duplicate delivery is normal recovery behavior and must not create a duplicate fill or command.

The feed is a result/state journal, not the participant's outbound request journal. Persist every submitted payload locally under client_request_id; pending replacements intentionally retain the prior effective order terms until DX confirms the mutation.

Lifecycle events

Event Meaning
order.admitted A canonical order was admitted by YM; it is not necessarily working at DXmatch.
order.working Venue evidence confirms the order is working.
order.replaced Venue evidence confirms the new single-order price/quantity is effective.
order.fill A fill and complete updated order snapshot are available.
order.cancelled Cancellation is effective.
order.expired The venue/lifecycle made the order terminal by expiry.
order.rejected The order was rejected and is terminal.
order.command_result Admission/outcome for NEW, REPLACE or CANCEL; a rejected NEW may have no order.

Every ordinary lifecycle event carries a complete canonical order snapshot. The sole orderless case is a schema-valid NEW rejected before an order could exist.

Relevant event fields include:

order.price_cents, order.filled_notional_cents, and fill.price_cents are all expressed in order.outcome. Clients never complement NO values.

Raw DXmatch replay offsets, MPID/account/session topology and the opposite participant's execution identifier are deliberately not exposed.

Control errors

The server may send stream.error and close the connection:

Code Action
INVALID_CURSOR Discard the cursor only after confirming the connection used the correct participant; reconnect without it for a fresh snapshot.
CURSOR_EXPIRED Reconnect without the cursor and rebuild nonterminal state from a fresh snapshot.
REPLAY_LIMIT_EXCEEDED Reconnect without the cursor; investigate why the client fell behind.
SLOW_CONSUMER Stop command flow, improve local consumption, then resume from last_written_cursor or the client's earlier safely applied cursor.
STREAM_ERROR Preserve the last safely applied cursor and reconnect with bounded backoff. Escalate persistent failures.

last_written_cursor means the last event written to the socket, not necessarily the last event your application applied. Prefer your own durable last-applied cursor.

Heartbeats and token rotation

Treat absence of both data and heartbeats beyond the announced interval plus a small network allowance as a disconnected session. Refresh the short-lived OAuth token out of band, open a replacement connection and resume from the last applied cursor.

Client-to-server application messages are not part of Private Feed v2. Standard WebSocket ping/pong may be used by the transport, but it does not acknowledge business events.

Forward path

The pilot feed already provides participant isolation, snapshot, replay and resume. Before contractual general availability, YM intends to complete multi-instance/high-availability evidence, retention and disaster-recovery proof, sustained slow-consumer testing and a published availability target. Future command WebSockets will share this canonical event stream rather than replace it.

7. Errors and retry policy

Status: trading-core canonical error envelope available; gateway-edge envelope and public versioned error registry in development

Canonical order errors use this shape:

{
  "code": "stale_market_generation",
  "message": "market generation is stale",
  "retryable": false,
  "command_id": null,
  "client_request_id": "strategy-a-new-42",
  "details": {}
}

The deprecated error field may duplicate message during transition. New clients should use code, message and retryable. Authentication, authorization, gateway rate-limit, and upstream-availability failures may still arrive as the transport-edge shape {"error":"..."}. Treat those as HTTP transport failures; do not infer a command outcome from that body.

HTTP policy

Status General meaning Client action
200 Read success, exact idempotent replay, or locally completed/no-op mutation. Inspect the canonical command and order.
201 A new order command was durably admitted. Wait for exchange-effective state.
202 A replace or venue-directed cancel was durably admitted. Wait for the corresponding effective event.
304 The order version matches If-None-Match. Keep the local snapshot.
400 Invalid request or unsupported contract value. Correct the request; do not blind-retry.
401 Missing, invalid or expired token. Obtain a valid token, then retry with the same command ID and payload.
403 Scope, account or policy denial. Do not retry until authorization/policy changes.
404 Resource not found in the participant scope. Reconcile identity; do not create a replacement identity blindly.
409 Current state conflicts with the command. Follow the specific code below.
429 Rate limit exceeded. Honor Retry-After; preserve command identity.
503 Required admission, reconciliation or rate-limit dependency unavailable. Follow retryable; use the same ID for an uncertain command.

Important validation codes

These require a corrected request rather than a retry:

Identity and idempotency conflicts

Code Meaning Action
idempotency_payload_conflict The NEW key already identifies a different payload. Generate a new key only for a genuinely new command.
replace_command_conflict / cancel_command_conflict The mutation key conflicts with an existing command payload. Reconcile the original command; do not overwrite its identity.
client_order_id_conflict The participant has retained that client order ID already. Reuse it only to recover the original order; otherwise choose a new order ID.
command_already_pending Another mutation is awaiting effective venue state. Wait for the private-feed outcome, refresh the order, then decide again.

Market and quote conflicts

Code Meaning Action
stale_market_generation The command used an old admission generation. Refresh the canonical market and re-evaluate the command.
market_not_open Lifecycle no longer accepts this command. Stop sending until a later canonical state explicitly permits it.
market_temporarily_unavailable Admission/readiness is currently blocked. Refresh state; retry only if the same command remains valid.
market_quote_unavailable The protected IOC quote could not be verified and the command was terminally rejected. Refresh the book and make a new economic decision under a new ID; replaying the old ID only recovers that rejection.
market_quote_no_liquidity No executable protected liquidity exists. Wait for book change or submit a different limit command with a new ID.
market_quote_moved The protected quote changed before admission. Refresh and consciously reprice using a new command identity.
market_quote_slippage_exceeded Available execution exceeded the supplied protection. Re-evaluate price protection; never auto-widen without strategy authority.

Replace conflicts

Code Meaning Action
order_not_replaceable The order is no longer in a replaceable working state. Refresh the order.
order_version_conflict expected_order_version is stale. Refresh and decide against the latest version.
replace_quantity_filled Target total does not exceed cumulative fills. Refresh fill state and choose a valid target.
replace_noop Target price and remaining quantity are already effective. Treat as no change; do not loop.
insufficient_replace_reserve Additional collateral/exposure is unavailable. Reduce/cancel or fund the account; do not blind-retry.
short_quantity_increase_not_supported This BUY NO order's total quantity cannot currently be increased safely. Cancel it and submit a separately collateralized NEW if still intended.

Coverage and participant policy

Uncertain outcomes

command_commit_unknown is the critical recovery case: YM could not prove to the caller whether the command transaction committed. Retry the exact command with the same Idempotency-Key. Do not generate a new key.

reconciliation_required means YM will not return or mutate uncertain canonical state. Stop mutation, preserve the last confirmed state and retry the read with bounded backoff. Escalate if it persists.

For connection loss or any HTTP timeout after request transmission:

  1. Do not infer failure.
  2. Retry the exact payload with the same key.
  3. Query orders and consume the private feed.
  4. Create a new command ID only after the original outcome is known and a new economic decision is made.

If a response or feed event contains a canonical command with admission_status=REJECTED, that identity is terminal even when its transport status was 503. Replaying it recovers the same rejection; it does not rerun admission.

Backoff

Use bounded exponential backoff with jitter for retryable transport and 5xx failures. Honor Retry-After on 429. Cancellation and risk-reducing traffic should use the separately provisioned cancellation capacity but must not spin without backpressure.

Forward path

YM intends to publish a generated, versioned registry containing every external error code, retry class and remediation, then enforce it against handler tests. Until that is complete, the curated OpenAPI plus this policy define the pilot contract; unknown codes must fail safe and be reported with correlation data.

8. Market data

Status: REST snapshots available; consumer WebSocket preview; professional recoverable stream in development

YM currently supports public REST snapshots and recent-trade reads suitable for discovery, command preflight and recovery checks. The existing consumer WebSocket is not yet the professional market-data contract.

L2 book snapshot

GET /v1/book?market_id={marketID}&depth={1..200}
GET /v1/markets/{marketID}/book?depth={1..200}

Depth defaults to 20 and is capped at 200 levels per side.

Example:

{
  "market_id": "immutable-market-id",
  "depth": 20,
  "bids": [
    {"price": 0.44, "price_cents": 44, "qty": 120}
  ],
  "asks": [
    {"price": 0.46, "price_cents": 46, "qty": 80}
  ],
  "seq": 184203,
  "updated_at": "2026-09-01T12:00:00Z"
}

Use price_cents when present. Decimal price exists for consumer compatibility.

seq is a monotonic YM market-data projection sequence for the running projection, not a durable professional replay cursor and not a DXmatch source sequence. updated_at is YM's projection timestamp; it must not be interpreted as an exchange-origin timestamp.

A closed or resolved market returns an empty book. An unknown/uninitialized market may also return an empty snapshot; always combine the book with canonical market lifecycle state.

Recent public trades

GET /v1/markets/{marketID}/trades?limit=200

This returns recent taker-side public trade activity with pseudonymous participants, side, liquidity role, price, quantity and occurrence time. It is not a participant's private drop copy; use Private Feed v2 for canonical own- order and fill recovery.

The L2 book and public trade tape use the common YES-book price coordinate. They do not switch coordinates for a participant's selected outcome.

The exact bridge is:

This complement is a market-data interpretation only. Public order commands always send their selected outcome price directly; clients must not complement NO order prices before submission.

Statistics

GET /v1/markets/{marketID}/stats

Statistics include 24-hour and total volume, trade/trader counts, average position and open interest. These are derived analytics and are not part of order admission or exchange-effective state.

Reference anchors

Provider anchors and price history are product/reference signals, not the YM order book and not executable prices. A strategy must not treat an anchor as a firm quote.

Consumer WebSocket preview

The existing endpoint is:

/v1/ws?markets=<csv>&streams=book_deltas,trades,ticker

It is intentionally not included in the market-maker OpenAPI. Its current sequence is local to a market-data service process, it does not provide the professional replay contract, and slow-consumer behavior is not suitable for market-making recovery. Its browser-oriented connection policy also differs from the headless private trading feed.

Do not build production market-making state solely from this preview.

Required client behavior today

Forward path

The professional market-data transport will be based on DXmatch-derived full book authority with bounded subscriptions, explicit fresh/stale state, coherent snapshot recovery, generation/lifecycle fencing and measured capacity. YM is evaluating the appropriate DX-native transport and will not manufacture replay guarantees the venue feed cannot support. The consumer WebSocket will either be upgraded behind an explicit professional contract or remain a separate retail presentation feed.

9. Limits, availability and roadmap

Status: controlled pilot policy; not a public SLA

Limits protect participant fairness, financial correctness and downstream venue capacity. They are keyed to authenticated identity where possible; a source-IP limit remains only a coarse pre-authentication denial-of-service boundary.

Current protocol limits

Resource Current limit
Idempotency key 200 characters; ym: prefix reserved
Client order ID 200 characters
Batch NEW Intended maximum 250 items; not enabled for v2 pilot
Batch CANCEL Intended maximum 250 items; not enabled for v2 pilot
Canonical order page 500 items maximum
Canonical market page 500 items maximum
Recent public market trades 200 items maximum
REST L2 depth 200 levels per side; default 20
Private-feed frame Server advertises max_frame_bytes; current profile caps at 256 KiB
Snapshot chunk At most 100 orders, and may be smaller to respect frame size

The server response is authoritative if a deployment advertises a narrower limit.

Current professional request profile

The controlled benchmark/onboarding profile is presently configured at 3,300 authenticated requests per minute. Professional cancel traffic uses an independent bucket from other professional requests, with the same current configured ceiling.

This value was selected to test a 50-command/second workload with control headroom. It is not an unlimited tier, a guaranteed sustained rate or a contractual SLA. A participant must honor 429 and Retry-After.

The pre-authentication IP limit is not participant identity. Approved clients must not assume that distributing requests across addresses increases their entitlement.

Availability matrix

Capability State Qualification
Canonical catalog REST Available Public discovery; canonical view required for trading.
L2 snapshot and public trade REST Available Snapshot/recovery reads, not a streaming SLA.
Canonical REST commands Pilot Approved accounts only.
Canonical account reads Pilot Self-scoped by bearer identity.
Private execution feed Pilot Resumable at-least-once delivery; contractual HA/SLO not yet published.
Batch commands In development Excluded until per-item replay and error-envelope conformance passes.
Consumer market-data WebSocket Preview Not approved as a professional recovery source.
Persistent command WebSocket In development Will reuse the canonical command path.
Recoverable professional market data In development DXmatch-derived snapshot/recovery design.
Mass cancel/cancel-on-disconnect/kill controls In development Required before broad external onboarding.
FIX In development Conditional on vendor access, conformance and measurable benefit.
External quote-set/mass-quote Not offered Internal Paper-LP routes are not an external contract.

Latency and capacity

YM measures end-to-end command latency from client request through canonical exchange-effective private-feed delivery, including p50, p95, p99, p99.9 and maximum observations. Internal benchmark results are evidence used to size the pilot; they are not an external guarantee until a workload, percentile, measurement boundary, exclusion policy and remedy are contractually published.

Capacity qualification must cover:

Current onboarding constraints

Roadmap to professional availability

Before expanding beyond controlled participants, YM intends to complete:

  1. Sustained release-grade command/fill benchmarks on exact deployed images.
  2. Persistent WebSocket order entry through the canonical command path.
  3. Recoverable professional market data.
  4. Mass cancel, cancel-on-disconnect and participant kill controls.
  5. Firm/application/strategy/account entitlement and credential lifecycle.
  6. Connection, subscription and outstanding-order quotas.
  7. Multi-instance private-feed and disaster-recovery evidence.
  8. A public status surface, changelog, conformance suite and support process.
  9. Published SLO and capacity terms based on measured workload and DXmatch tenant capacity.

These are forward-looking integration notes, not current commitments or dates. Capabilities remain unavailable until their status is changed in a versioned participant contract.