Understanding OEMS Guide

This guide is meant to help users understand how to use Moment's Orders API. The same guide can be found at the top of the Orders API as well.

Using the Moment Orders API, a Client can monitor, place, and cancel their orders with Moment. Each order has a unique identifier that will be returned as part of the order object, along with the rest of the fields described below. Once an order is placed, it can be queried using the system-assigned unique ID to check the status. Updates on open orders at Moment will also be sent over the Real-time Orders API, which is the recommended method of maintaining order state.

Glossary

  • Order — The order created via POST /v1/trading/order/.
  • Execution Order (EO) — A discrete set of execution instructions created against an Order (e.g., LOB SOR, Manual RFQ, AutoEx RFQ, External).
  • Allocation — Pre-trade account splits attached to an Order that determine how fills are booked.

Creating Orders

Clients can submit requests to purchase or sell fixed income securities through the POST /v1/trading/order/ endpoint:

POST /v1/trading/order/
{
  "account_id": "eb9e2aaa-f71a-4f51-b5b4-52a6c565dad4",
  "instrument_id": "037833DP2",
  "amount": { "par": 3000.0 },
  "type": "limit",
  "side": "buy",
  "limit_price": 99.5,
  "extended_hours": false
}

After submitting an order request like the one above, the Client receives a unique ID for the order. This ID can then be supplied to the GET /v1/trading/order/{id}/ endpoint to retrieve the corresponding order object. The order object includes both information about the Client’s request (e.g., account ID, limit price, quantity, direction), as well as information about the current state of the request (e.g., filled quantity, filled average price).

Some order fields are immutable and will never change throughout the life of an order: id, isin, cusip, amount, type, side, limit_price, extended_hours. Other order fields are mutable and will change in response to order events: filled_amount, filled_avg_price, status.

GET /v1/trading/order/mo_V1StGXR8_Z5jdHi6B-myT/
{
  "id": "mo_V1StGXR8_Z5jdHi6B-myT",
  "account_id": "eb9e2aaa-f71a-4f51-b5b4-52a6c565dad4",
  "created_at": "2021-03-16T18:38:01.942282Z",
  "approved_at": "2021-03-16T18:38:01.937734Z",
  "filled_at": null,
  "canceled_at": null,
  "isin": "US037833DP29",
  "cusip": "037833DP2",
  "amount": { "par": 3000.0 },
  "filled_amount": { "par": 1 },
  "filled_avg_price": { "pop": 90, "ytm": 4.6 },
  "type": "limit",
  "side": "buy",
  "limit_price": 99.5,
  "status": "partially_filled",
  "extended_hours": false
}

Executing an Order

When you create an Order, there are three ways it can move into execution:

1) Automated Execution (rules-based)

If your organization has configured an Execution Instruction Ruleset, orders will automatically be routed according to those rules. For example, your rules might direct corporate bonds over 1MM par to RFQ AutoEx, while smaller orders route via Smart Order Routing (SOR).

  • OMS accepts and approves the order.
  • Ruleset proposes protocol + strategy.
  • OMS issues an Execution Order to EMS.
  • You’ll see execution-order events like execution_order_create, followed by trade execution events (fills).

Tip: To stage instead of auto-executing, set "bypass_auto_execution": true on the order request.


2) Manual Execution at Order Creation

Provide execution instructions directly on the order request without relying on rules (e.g., Manual RFQ against a specific quote, or Manual LOB to a venue).

  • OMS accepts the order (pending_execution).
  • OMS issues an Execution Order to EMS based on the instructions you supplied.
  • Execution-order events (execution_order_create/cancel) stream back, and fills update the Order.

3) Manual Execution via Staged Orders

If no rules apply, or if you use "bypass_auto_execution": true, the order stages in pending_execution. From there, create Execution Orders separately using the Execution Order APIs. This lets you split an Order across multiple execution orders or try different protocols sequentially.

  • OMS accepts the order and stages it.

  • No execution occurs until you submit an Execution Order.

  • Post to endpoints such as:

    • POST /v1/trading/order/\{id\}/execution-order/lob/sor/
    • POST /v1/trading/order/\{id\}/execution-order/lob/manual/
    • POST /v1/trading/order/\{id\}/execution-order/rfq/manual/
    • POST /v1/trading/order/\{id\}/execution-order/rfq/autoex/
    • POST /v1/trading/order/\{id\}/execution-order/external/

Key Things to Know

  • bypass_auto_execution Forces staging even if rules are configured. Use this to prevent rules-driven auto-execution.

  • Manual vs. External trade reporting For off-platform trades, use protocol external (via Execution Order APIs) and submit an external trade report so OMS can track, book, and allocate consistently. If you have already booked the trade outside the system and only need to report it for record-keeping, set bypass_trade_booking: true on the external trade report you submit.

  • Fees on orders You can pass fees on the order which override the default fees configured in the system for the risk_group_id.

  • Events Orders emit top-level lifecycle events (request, approve, reject, cancel, execution). Execution Orders emit their own sub-events (execution_order_create, execution_order_cancel).

  • Events coverage window The Events API returns events from the last 2 days. For durable state, consume the Real-time Orders API and persist events in your system.


Block Trading & Pre-Trade Allocations

To submit a block trade, include allocations on the order request. This creates an Allocation object for the order at creation time.

Current behavior: Moment only supports pre-trade allocations. Allocations must be supplied on the initial order request (post-trade allocation entry is not supported).

How it works

  1. You submit an order with an allocations object (pre-trade).
  2. The system creates an Allocation linked to the Order.
  3. As fills come in, the Allocation is calculated and then submitted to the custodian for booking based on your strategy.
  4. You receive real-time allocation events over the Events/Real-time Orders API.

Example — order with pre-trade allocations

{
  "client_order_id": "01JZ5Q165940HX2Q3SB2EK0CA4",
  "instrument_id": "00033GAB1",
  "limit_price": null,
  "type": "market",
  "extended_hours": true,
  "side": "buy",
  "amount": { "type": "par", "value": 10000 },
  "account_id": "",
  "ib_id": "01K4BRMF8MCV09YXYE1TT4S2TB",
  "risk_group_id": "01K4BRMRH4ERKRYFCJKCQYKR26",
  "execution_instructions": [
    {
      "protocol": "limit_order_book",
      "strategy": "smart_order_routing",
      "quantity": { "type": "par", "value": 10000 },
      "limit_price": 84.35,
      "suppress_pmp_check": false,
      "all_or_none": true,
      "client_execution_order_id": "01K4BRMZZPD8BD896GB4PC3VF4"
    }
  ],
  "explicit_cancelation_required": true,
  "trader_profile": {
    "user_id": "01K4BRN66KX4977GWNTBKMSKWW",
    "bloomberg_id": "BBG000BLNQ16"
  },
  "custodian_id": "cust_lpl",
  "allocations": {
    "strategy": "fifo_without_averaging",
    "client_allocation_id": "allocation-01K4BRNB4YV87WZV9G5DA2QTT4",
    "account_allocations": [
      {
        "client_account_allocation_id": "allocation-01K4BRNJ2VJJKQ0C6VZWWT734J",
        "account_id": "myaccount",
        "requested_amount": { "type": "par", "value": 10000 }
      }
    ]
  },
  "all_or_none": true
}

Real-time allocation events

System events

  • cancel_allocation_request — Request to cancel an allocation.
  • cancel_allocation_reject — Rejection on the cancel request.

Order events

  • allocation_create — Allocation object created for the order.
  • allocation_calculate — Engine computed splits based on executions (with account_allocations.actual_amount, fill_price, and venue info).
  • allocation_submit — Allocation submitted to the custodian for booking (includes custodian_id).
  • allocation_approve — Allocation approved.
  • allocation_reject — Allocation rejected (code, reason).
  • allocation_fail — Booking/processing failure (code, reason).
  • allocation_cancel — Allocation canceled.

Canceling an allocation

DELETE /v1/trading/allocation/{allocation_id}/

EO Endpoint Cheat Sheet

ActionEndpoint
LOB SOR EOPOST /v1/trading/order/\{id\}/execution-order/lob/sor/
LOB Manual EOPOST /v1/trading/order/\{id\}/execution-order/lob/manual/
RFQ Manual EOPOST /v1/trading/order/\{id\}/execution-order/rfq/manual/
RFQ AutoEx EOPOST /v1/trading/order/\{id\}/execution-order/rfq/autoex/
External EOPOST /v1/trading/order/\{id\}/execution-order/external/
Report external tradePOST /v1/trading/order/\{id\}/execution-order/{execution_order_id}/external/trade-report/
Cancel EODELETE /v1/trading/order/\{id\}/execution-order/{execution_order_id}/

Review & Release (Flagged Orders)

On order submission, Moment runs your org’s pre-trade controls. If an order fails one or more controls that are marked as soft controls (i.e., control remediation is flag), it is flagged for review and a human is required to explicitly approve or reject it. If all of your controls have remediation reject, no orders will be flagged for review.

What you’ll see

  • Order remains in pending_approval.
  • Auto-routing is paused (no Execution Orders are created).
  • You receive an order_updateflagged_for_review event with details.
{
  "msg_type": "order_update",
  "order": { "id": "mo_..." },
  "event": {
    "event_type": "flagged_for_review",
    "time": "2025-01-02T15:04:05Z",
    "order_id": "mo_...",
    "client_order_id": "co-123",
    "failed_controls": [
      { "control_message": "Price outside configured tolerance." },
      { "control_message": "Trader not entitled for this instrument." }
    ]
  },
  "event_id": "evt_..."
}

Approving or Rejecting a flagged order

A system administrator (per your org’s entitlements) must take action on the Order.

  1. Request the action — you’ll receive a system_update acknowledging the request:

    • manual_approve_request
    • manual_reject_request
{
  "msg_type": "system_update",
  "event": {
    "event_type": "manual_approve_request",
    "time": "2025-01-02T15:05:10Z",
    "order_id": "mo_...",
    "manual_approve_id": "ma_01...",
    "client_manual_approve_id": "client-ma-123",
    "annotation": "Approved per desk head"
  },
  "event_id": "evt_..."
}

If the request cannot be accepted, you’ll receive a failure:

  • manual_approve_fail (with reason)
  • manual_reject_fail (with reason)
  1. Decision & release — you’ll receive an order_update:
  • approve — Order → pending_execution
  • reject — Order → rejected

Orders Submitted Outside of Eligible Trading Hours

Orders not eligible for extended hours submitted after 4:00pm ET will be rejected.


Extended Hours Trading

Clients can submit and fill orders during pre-market and after-hours.

Currently, we support full extended hours:

  • Pre-market: 7:30am – 9:30am ET (Mon–Fri)
  • After-hours: 4:00pm – 5:00pm ET (Mon–Fri)

Note: In live trading, extended hours run 7:30am–5:00pm ET.

Submitting an Extended Hours Eligible Order

To indicate an order is eligible for extended hours trading, supply a boolean parameter named extended_hours on the order request. When this parameter is true, the order is eligible for execution in the pre-market or after-hours. All bonds supported during regular market hours are also supported during extended hours.


Time in Force

All orders submitted via Moment are day orders. A day order is eligible for execution only on the day it is live. By default, the order is valid during Regular Trading Hours (9:30am – 4:00pm ET). If unfilled by 4:00pm ET, it automatically expires. If submitted after the close, it is rejected. However, if marked as eligible for extended hours, the order can also execute during supported extended hours.


Canceling Orders

Clients can request to cancel an open order through the endpoint:

DELETE /v1/trading/order/my_order_id/

When a Client submits a cancellation request for an order, Moment will attempt to cancel any outstanding order tickets on the trading venues. A cancel request will be rejected if the order is closed, nonexistent, or if a cancel request is already pending.

Coupling parent/child cancellations (explicit_cancelation_required)

Control whether an Order is automatically canceled when its single Execution Order is canceled:

  • explicit_cancelation_required: false (default) If the Order has exactly one Execution Order and that Execution Order is canceled, the Order will also be canceled automatically.

  • explicit_cancelation_required: true The Order will not auto-cancel when its Execution Order is canceled. You must explicitly cancel the Order via DELETE /v1/trading/order/\{id\}/ if desired.