This guide is meant to help users understand how to use Moment's Orders API.
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 tradeexecutionevents (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 protocolexternal(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, setbypass_trade_booking: trueon the external trade report you submit. -
Fees on orders
You can passfeeson the order which would 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.
Execution Orders
In addition to submitting Orders, Clients can create Execution Orders on top of staged orders. Execution Orders represent specific execution instructions for how an Order should be worked by Moment’s Execution Management System (EMS).
Execution Orders allow Clients to:
- Break down an Order into one or more distinct execution strategies.
- Route via different protocols such as SOR, Manual RFQ, Auto RFQ, or External trade reporting.
- Cancel and issue new execution requests independently of the Order.
Execution Order prerequisites & limits
-
order status must be
pending_executionorpartially_filled. -
You may create multiple execution orders; the sum of their open quantities must not exceed the order’s open quantity.
-
Each request must include a
client_execution_order_id(idempotency). -
Protocol-specific requirements:
- LOB Manual: include
venue_mpid. - AutoEx RFQ: include
rfq_protocol_parameters,execution_criteria, andexit_criteria(and optionallyskip_lob_quotes). - External: you may attach an
external_trade_reportinline or report it later to the EO.
- LOB Manual: include
Execution Order Lifecycle
Execution Orders have their own lifecycle and event updates, distinct from the Order. Clients receive real-time updates over the Real-time Orders API.
System events
execution_order_request— Acknowledges Moment received the request.execution_order_reject— Request rejected due to validation/state errors.execution_order_cancel_request— Acknowledges a cancel was requested on the execution order.execution_order_cancel_reject— Cancel request rejected.
Order events
execution_order_create— Execution order accepted and staged/sent to EMS routing.execution_order_cancel— Execution order canceled successfully.
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).
RIA accounts must use
fifo_without_averaging. The averaging
strategies (fifo_with_averaging,pro_rata_with_averaging) require a
principal/averaging trading account to average executions before they are
booked to client accounts. RIAs trade in an agency capacity and must report
the actual street-execution prices and quantities to their custodian (e.g.
Schwab), so each allocation has to match a real executed trade. Because there
is no averaging account to absorb the difference, averaged allocation is not
available to RIAs — only the non-averaging FIFO strategy, which preserves the
true per-trade execution prices, is supported.
How it works
- You submit an order with an
allocationsobject (pre-trade). - The system creates an Allocation linked to the Order.
- As fills come in, the Allocation is calculated and then submitted to the custodian for booking based on your strategy.
- 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— Allocation engine computed splits based on executions (returnsaccount_allocationswithactual_amount,fill_price, and any linked venue info).allocation_submit— Allocation submitted to the custodian for booking (includescustodian_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
| Action | Endpoint |
|---|---|
| LOB SOR EO | POST /v1/trading/order/{id}/execution-order/lob/sor/ |
| LOB Manual EO | POST /v1/trading/order/{id}/execution-order/lob/manual/ |
| RFQ Manual EO | POST /v1/trading/order/{id}/execution-order/rfq/manual/ |
| RFQ AutoEx EO | POST /v1/trading/order/{id}/execution-order/rfq/autoex/ |
| External EO | POST /v1/trading/order/{id}/execution-order/external/ |
| Report external trade | POST /v1/trading/order/{id}/execution-order/{execution_order_id}/external/trade-report/ |
| Cancel EO | DELETE /v1/trading/order/{id}/execution-order/{execution_order_id}/ |
Order States and Statuses
An order’s status tells API users where the order currently is in its lifecycle. There are seven possible order statuses: pending_approval, pending_review, pending_execution, partially_filled, filled, rejected, and canceled.
Moment considers orders whose statuses are pending_approval, pending_review, pending_execution, or partially_filled to be in the open state, meaning they are actively being processed and their statuses may change. Orders whose statuses are filled, rejected, or canceled are in the closed state, meaning they are no longer being processed and their statuses will not change.
| Status | State | Description | Possible Next States |
|---|---|---|---|
pending_approval | open | The order has been received and is waiting for approval. | pending_review rejectedcanceledpending_execution |
pending_review | open | The order has been received and is waiting manual approval. | rejectedcanceledpending_execution |
pending_execution | open | The order has been approved and Moment is attempting to execute the order. | partially_filledfilledcanceled |
partially_filled | open | The order has been partially filled by one or more executions, and Moment is continuing to attempt to execute the remainder. | partially_filledfilledcanceled |
filled | closed | The order has been filled. No further updates will occur. | None |
canceled | closed | The order has been canceled by the client, Moment, or the venue. No further updates will occur. Note that canceled orders may have been partially filled prior to cancellation. | None |
rejected | closed | The order has been rejected by Moment. No further updates will occur. | None |
Order Status Descriptions
-
pending_approval— The order has been received by Moment and is awaiting approval. While in this status, no execution activity will take place. The order will transition topending_executionupon approval,rejectedif a reviewer declines it, orcanceledif a cancellation request is submitted. -
pending_review— The order has been received by Moment and is awaiting manual approval. This status occurs when an order is flagged by one or more soft pre-trade controls and requires a human reviewer to explicitly approve or reject it. While in this status, no execution activity will take place. The order will transition topending_executionupon approval,rejectedif a reviewer declines it, orcanceledif a cancellation request is submitted. -
pending_execution— The order has been approved and is staged for execution. Moment is actively attempting to execute the order, or the order is waiting for the client to submit Execution Orders (in the case of staged orders withbypass_auto_execution: true). The order will transition topartially_filledorfilledas executions occur, or tocanceledif a cancellation is requested. -
partially_filled— The order has received one or more fills but the full requested amount has not yet been executed. Moment continues to work the remaining quantity. The order will transition tofilledonce the entire amount is executed, remainpartially_filledas additional fills come in, or move tocanceledif a cancellation is requested. Note that a canceled order may have partial fills — checkfilled_amountto determine how much was executed before cancellation. -
filled— The order has been completely filled. The entire requested amount has been executed and no further updates will occur. This is a terminal (closed) status. Thefilled_amountandfilled_avg_pricefields reflect the final execution results. -
canceled— The order has been canceled by the client, by Moment, or by the trading venue. No further execution activity will occur. This is a terminal (closed) status. A canceled order may have been partially filled prior to cancellation — always checkfilled_amountto see if any quantity was executed before the order was canceled. -
rejected— The order has been rejected by Moment. This can happen when a reviewer explicitly rejects a flagged order, when the order fails hard pre-trade controls, or when the order is submitted outside of eligible trading hours. No execution activity will occur. This is a terminal (closed) status.
Order Types
When a Client submits an order, they can choose one of the supported order types. Due to lower liquidity in the bond market as compared with the equity market, most fixed income trading venues do not support market orders.
Limit Order
A limit order is an order to buy or sell at a specified price or better. A buy limit order is executed at the specified limit price or lower (better). A sell limit order is executed at the specified limit price or higher (better). Clients must specify the limit_price when submitting an order.
While a limit order can prevent slippage, it may not be filled for some time—if at all. For a buy limit order, if the market price is within the specified limit price, Clients can expect the order to be filled. If the market price is equivalent to the limit price, the order may or may not be filled; if it cannot immediately execute against resting liquidity, it is deemed non-marketable and will only be filled once a marketable order interacts with it.
Market Order
A market order is an instruction to buy or sell at the best available price. Market orders do not include a limit_price and can be subject to slippage if liquidity is thin.
- Availability of market orders varies by instrument/venue in fixed income. If a venue does not support market orders for the given instrument, the request may be rejected.
- Market orders can partially fill; any unfilled remainder will continue to work or be rejected based on venue behavior and time-in-force.
- Use with care during extended hours or in illiquid securities due to wider spreads.
- Market orders will only execute within the price controls set up by the executing broker.
Example (if supported):
POST /v1/trading/order/
{
"account_id": "eb9e2aaa-f71a-4f51-b5b4-52a6c565dad4",
"instrument_id": "037833DP2",
"amount": { "par": 3000.0 },
"type": "market",
"side": "buy",
"extended_hours": false
}All-or-None (AON)
All-or-None is an order constraint, not a separate order type. When AON is set, the instruction is to fill the entire requested amount or none—no partial fills.
You can set all_or_none to true on the order to restrict the order to only have 1 fill. You can also opt to let the order not be all or none & instead enforce the constraint only on the execution orders.
Example (AON on a Manual RFQ Execution Order):
POST /v1/trading/order/{id}/execution-order/rfq/manual/
{
"client_execution_order_id": "exec-002",
"amount": { "par": 500000 },
"all_or_none": true,
"rfq": {
"id": "rfq-123",
"contra_quote_id": "quote-456"
}
}Example (AON inside execution instructions on order creation):
POST /v1/trading/order/
{
"account_id": "eb9e2aaa-f71a-4f51-b5b4-52a6c565dad4",
"instrument_id": "037833DP2",
"amount": { "par": 500000 },
"type": "limit",
"side": "buy",
"limit_price": 99.5,
"execution_instructions": [
{
"protocol": "request_for_quote",
"strategy": "manual",
"all_or_none": true,
"rfq": { "id": "rfq-123", "contra_quote_id": "quote-456" }
}
]
}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 they have the control remediation set to flag), it is flagged for review and a human is required to explicitly approve or reject it. If all of your controls are set with remediation of reject, then you would not have the case where an order is ever flagged for review.
What you’ll see
- Order in
pending_review. - Auto-routing is paused (no Execution Orders are created).
- You receive an
order_update→flagged_for_reviewevent with details.
Example — flagged_for_review event (excerpt):
{
"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:
- Request the action
When an approval (or rejection) request is submitted, you’ll receive asystem_updateacknowledging the request.
manual_approve_request(acknowledges an approval request)manual_reject_request(acknowledges a rejection request)
Example — manual_approve_request (excerpt):
{
"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 (e.g., invalid state or permissions), you’ll receive a failure:
manual_approve_fail(withreason)manual_reject_fail(withreason)
- Decision & release
Once an admin completes the review, you’ll receive anorder_update:
approve— the Order transitions topending_execution.reject— the Order transitions torejectedand will close immediately.
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:30pm ET (Mon–Fri)
Note: In live trading, extended hours run 7:30am–5:30pm 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 DELETE /v1/trading/order/{id}/ endpoint:
DELETE /v1/trading/order/mo_V1StGXR8_Z5jdHi6B-myT/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)
explicit_cancelation_required)You can 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 viaDELETE /v1/trading/order/{id}/if desired.