Model Orders

Allocate many client accounts to an evergreen fund as a single block, with requirements evaluated in bulk and every account filled at the same price.

A Model Order places one order per account, for many accounts, as a single block. It is designed for advisor and model portfolio platforms, where one decision - adding a fund to a model, or rebalancing it - produces orders across a book of client accounts. Monark treats the orders in a Model Order as a block, and fills every one of them at the same price.

You build a Model Order in steps: create it as a draft, add the accounts' orders in one or more batches, then complete it. Model Orders work this way from API version 1.6.1. Earlier versions took every order in the create request.

If your platform places one order at a time, you do not need Model Orders. See Subscriptions (Buy Orders).

Endpoints used

MethodEndpointPurpose
POST/primary/v1/omnibus/order-action/requirements/batchEvaluate requirements for every account in one request
PUT/primary/v1/omnibus/order-action/requirements/{definitionId}/completeReport a completed requirement for one account
POST/primary/v1/omnibus/model-orderCreate a draft Model Order
POST/primary/v1/omnibus/model-order/investor-ordersAdd a batch of per-account orders to a draft
POST/primary/v1/omnibus/model-order/completeSubmit a draft for processing
GET/primary/v1/omnibus/model-orderList Model Orders
GET/primary/v1/omnibus/model-order/{id}Retrieve a Model Order with its per-account orders
POST/primary/v1/omnibus/model-order/cancelRequest cancellation of a Model Order and all of its orders

How Model Orders are structured

LevelCarries
Model Order (parent)Fund, share class, side, currency, distribution election, tax lot election, routing, your referenceId, and your modelId
Order (one per account)accountId, financialAdvisorId, its own referenceId, and an amount

Every order inherits the parent's fund, share class, side, and elections. This has two consequences for how you translate a model into API calls:

ScenarioSubmit
A model allocates to several evergreen fundsOne Model Order per fund. Send the same modelId on each, so they can be tied back to the model.
A rebalance buys for some accounts and sells for othersTwo Model Orders: a Buy with dollar amounts, and a Sell with share quantities.

Workflow

  1. The model strategist chooses the evergreen fund and share class to allocate to, and the target weight within the model.
  2. The advisor chooses the client accounts that will track the model.
  3. Your platform calculates each account's order amount from the account's value and the model's weights.
  4. Evaluate requirements for every account in one batch request, and collect what is outstanding. We recommend presenting all the suitability requirements for the evergreen funds in the model when the Advisor is allocating the client into the model.
  5. Create the Model Order, add the per-account orders, and complete it.
  6. Track the Model Order and its per-account orders.

Sizing each account's order is your platform's logic. Validate every calculated amount against the share class minimums before you submit, as described in Subscriptions (Buy Orders), and let the advisor exclude accounts that fall below them.

Evaluate requirements in bulk

POST /primary/v1/omnibus/order-action/requirements/batch
{
  "omnibusFundId": "d4f6b8c0-0000-4000-8000-0000000000f1",
  "omnibusShareClassId": "e5a7c9d1-0000-4000-8000-0000000000c1",
  "side": "Buy",
  "orders": [
    { "accountId": "b2d4e6f8-0000-4000-8000-000000000021", "financialAdvisorId": "c3e5a7b9-0000-4000-8000-000000000031" },
    { "accountId": "b2d4e6f8-0000-4000-8000-000000000022", "financialAdvisorId": "c3e5a7b9-0000-4000-8000-000000000031" }
  ]
}

This request evaluates requirements only. It does not create or change anything.

{
  "allSatisfied": false,
  "orders": [
    {
      "accountId": "b2d4e6f8-0000-4000-8000-000000000021",
      "financialAdvisorId": "c3e5a7b9-0000-4000-8000-000000000031",
      "evaluationSucceeded": true,
      "errorCode": null,
      "errorMessage": null,
      "allSatisfied": false,
      "actions": [
        {
          "definitionId": "5c1d8a52-0000-4000-8000-0000000000d1",
          "name": "Acknowledge Subscription Process",
          "type": "TextAcknowledge",
          "responsibleParty": "Advisor",
          "status": "Required"
        }
      ]
    },
    {
      "accountId": "b2d4e6f8-0000-4000-8000-000000000022",
      "financialAdvisorId": "c3e5a7b9-0000-4000-8000-000000000031",
      "evaluationSucceeded": true,
      "errorCode": null,
      "errorMessage": null,
      "allSatisfied": true,
      "actions": []
    }
  ]
}
FieldDescription
allSatisfied (top level)true only when every account is satisfied. Gate the submit button on this.
orders[]One result per account, in the order you sent them.
orders[].evaluationSucceededfalse when the account could not be evaluated. errorCode and errorMessage say why.
orders[].allSatisfiedWhether this account has anything outstanding.
orders[].actions[]The account's requirements, in the shape described in Pre-Order Requirements.

Important: Send each account's financialAdvisorId in the batch request, exactly as you will send it when you add the account's order. If the advisor is omitted, advisor-responsible requirements are not returned, the batch can report allSatisfied: true, and the account's order is then refused with RequiredOrderActionsIncomplete.

Present requirements across accounts

Most requirements in a Model Order are identical across accounts. Showing the same disclosure once per account does not scale past a handful of clients, so group the results by definitionId and show one row per requirement, with a count of the accounts that have satisfied it.

UI elementSourceNotes
Requirementactions[].name, actions[].markdownText or actions[].actionTextGrouped by definitionId.
Responsible partyactions[].responsibleParty
ProgressAccounts where the requirement is Satisfied ÷ accounts where it appliesFor example, "2/3 accounts".
Outstanding totalCount of distinct requirements with at least one account Required
Unevaluated accountsorders[] where evaluationSucceeded is falseList separately, with errorMessage. Never count these as satisfied.

When the advisor completes a grouped requirement, call the complete endpoint once for each account where it is Required, sending that account's accountId and financialAdvisorId. Then run the batch evaluation again.

Requirements whose responsibleParty is Investor or CoOwner are addressed to the client, not to the advisor. Agree with your compliance team whether they are routed to the client, or whether the advisor may attest to them under your firm's procedures. Where they are routed to the client, hold the account out of the Model Order until they are complete. Questionnaire requirements are answered per account, as described in Pre-Order Requirements.

Submit the Model Order

A Model Order is submitted in three steps:

StepCallResult
1. CreatePOST /primary/v1/omnibus/model-order201. The Model Order is created with a status of Draft.
2. Add ordersPOST /primary/v1/omnibus/model-order/investor-orders200. Repeat for each batch of accounts. The Model Order stays Draft.
3. CompletePOST /primary/v1/omnibus/model-order/complete202. The Model Order moves to Processing, and its outcome is sent by webhook.

Complete the Model Order on the day you create it. A draft that is still open at 1:00 AM Eastern is cancelled, with a statusReasonCode of DraftExpired, and OmnibusModelOrderCancelled is sent. The time you complete the Model Order is its submission time, so complete it before Monark's cutoff for the dealing date you want.

1. Create the draft

POST /primary/v1/omnibus/model-order
IdempotencyKey: 1d9b7e52-3c44-4f0a-8e6b-5a2f9c7d1e30
{
  "referenceId": "MOD-2026-000042",
  "modelId": "Balanced Growth 60/20/20",
  "financialInstitutionId": "7f3c2a10-0000-4000-8000-000000000001",
  "omnibusFundId": "d4f6b8c0-0000-4000-8000-0000000000f1",
  "omnibusShareClassId": "e5a7c9d1-0000-4000-8000-0000000000c1",
  "side": "Buy",
  "currency": "USD",
  "distributionElection": "Drip",
  "taxLotElection": "FIFO"
}
FieldRequiredDescription
referenceIdYesYour identifier for the Model Order, up to 100 characters. Must be unique per partner.
modelIdNoYour identifier for the model or rebalance, up to 100 characters. Shared across the Model Orders of one model.
financialInstitutionIdYesThe custodian that holds every account in the Model Order. Each account's owner and advisor must be at this custodian.
omnibusFundId, omnibusShareClassIdYesThe fund and share class every order trades.
sideYesBuy or Sell.
currencyYesUSD.
distributionElectionYesCash or Drip. Applies to every order.
taxLotElectionYesFIFO, LIFO, HCFO, or LCFO. Applies to every order.
routeInstructionNoTransferAgent (the default) or IntraCustodianNetting. Applies to every order.
unnettedOrderRoute, nettingTif, nettingTifDateNoNetting orders only. Apply to every order. See Subscriptions (Buy Orders).

The draft is checked when you create it: the fund and share class, the custodian's access to the fund, and the omnibus account for the custodian, share class and distribution election. A refused draft is not stored. The response carries the draft's id, which the next two steps need.

{
  "id": "8a4c2e60-0000-4000-8000-0000000000a1",
  "externalId": "01a0b5c3e2f4d6a8b0c2",
  "referenceId": "MOD-2026-000042",
  "status": "Draft",
  "submittedAtUtc": "2026-09-18T15:04:12.381Z",
  "requestedRouteInstruction": null,
  "routeInstruction": "TransferAgent",
  "statusReasonCode": null,
  "message": null,
  "rejectedOrderReferenceId": null,
  "fieldErrors": [],
  "receivedOrderCount": 0
}

2. Add the orders

POST /primary/v1/omnibus/model-order/investor-orders
{
  "modelOrderId": "8a4c2e60-0000-4000-8000-0000000000a1",
  "orders": [
    {
      "referenceId": "MOD-2026-000042-01",
      "accountId": "b2d4e6f8-0000-4000-8000-000000000021",
      "financialAdvisorId": "c3e5a7b9-0000-4000-8000-000000000031",
      "notionalAmount": 50000
    },
    {
      "referenceId": "MOD-2026-000042-02",
      "accountId": "b2d4e6f8-0000-4000-8000-000000000022",
      "financialAdvisorId": "c3e5a7b9-0000-4000-8000-000000000031",
      "notionalAmount": 32500
    }
  ]
}
FieldRequiredDescription
modelOrderIdYesThe draft's id.
orders[]YesOne line per account. A Model Order holds up to 10,000 lines across all its batches, and an account can appear in it only once.
orders[].referenceIdYesYour identifier for the account's order, up to 100 characters. Must be unique per partner, and can't already be on this or another open Model Order.
orders[].accountIdYesThe account.
orders[].financialAdvisorIdConditionalThe account's advisor. Must match the batch evaluation.
orders[].notionalAmountFor BuyDollars, greater than zero, up to 2 decimal places. Omit quantity.
orders[].quantityFor SellShares, greater than zero, up to 6 decimal places. Omit notionalAmount.

Monark checks every line in the batch as it arrives: the account, its owner and advisor, accreditation, requirements, sellable shares for a Sell, the share class minimum for a Buy, and the custodian's per-order and daily limits. If any line fails, the whole batch is refused and none of it is added. The Model Order stays Draft and keeps the batches already added. The response names the check in statusReasonCode and, when one line caused it, the line in rejectedOrderReferenceId, so you can correct the line, or leave the account out, and send the batch again. For example, a batch refused with 409 because one account has open requirements:

{
  "id": "8a4c2e60-0000-4000-8000-0000000000a1",
  "externalId": "01a0b5c3e2f4d6a8b0c2",
  "referenceId": "MOD-2026-000042",
  "status": "Draft",
  "submittedAtUtc": "2026-09-18T15:04:12.381Z",
  "requestedRouteInstruction": null,
  "routeInstruction": "TransferAgent",
  "statusReasonCode": "RequiredOrderActionsIncomplete",
  "message": "Individual order MOD-2026-000042-02 has incomplete required order actions.",
  "rejectedOrderReferenceId": "MOD-2026-000042-02",
  "fieldErrors": [],
  "receivedOrderCount": 0
}

An accepted batch returns 200 with the same body, and the reason fields are null. receivedOrderCount is the number of lines added to the Model Order so far. Send batches one at a time: two batches sent to the same draft at once can be refused with 409 (ModelOrderModifiedConcurrently).

3. Complete the Model Order

POST /primary/v1/omnibus/model-order/complete
{
  "modelOrderId": "8a4c2e60-0000-4000-8000-0000000000a1",
  "totalOrderCount": 2
}

totalOrderCount is the number of lines you added across all batches. If it doesn't match receivedOrderCount, the request is refused with 409 (OrderCountMismatch) and the Model Order stays Draft, so a lost batch can't go unnoticed. Otherwise the response is 202 with a status of Processing. A Processing Model Order can't take more lines or be cancelled.

Monark then checks every line again, because holdings, limits and requirements can change after a batch is added, and creates the per-account orders. One account that fails a check now rejects the whole Model Order. The outcome is sent by webhook, and you can also retrieve the Model Order to see it:

OutcomestatusWebhook
AcceptedReceivedOmnibusModelOrderCreated. The per-account orders are created and listed in orders[].
A line failed a checkRejectedOmnibusModelOrderRejected. statusReasonCode names the check, and rejectedOrderReferenceId the line when one line caused it. No per-account orders are created.
Couldn't be processedFailedOmnibusModelOrderFailed, for example with ModelOrderProcessingFailed or SettlementPublishFailed. Contact Monark Operations before resubmitting.

As with individual orders, branch on status and do not rely on the HTTP code alone.

Retries

Every step can be retried safely after a timeout, because a repeated call is refused rather than applied twice:

CallIf the first call succeeded, the retry returnsWhat to do
Create409 (DuplicateReferenceId)Find the draft with GET /primary/v1/omnibus/model-order?referenceId={referenceId}.
Add orders409 (DuplicateOrderReferenceId), naming a line that was already addedRetrieve the Model Order and check receivedOrderCount.
Complete409 (ModelOrderNotDraft), with the Model Order's current status in the bodyTrack the Model Order from that status.

When a model spans several funds, you submit several Model Orders. Report the outcome of each one separately, so a rejected fund does not hide an accepted one, and so the advisor can correct and resubmit only what failed.

Track Model Orders

GET /primary/v1/omnibus/model-order?financialInstitutionId={financialInstitutionId}&modelId={modelId}
Query parameterDescription
financialInstitutionIdModel Orders for accounts held at one custodian.
accountIdModel Orders that include the account.
modelIdModel Orders submitted for one model.
omnibusFundId, omnibusShareClassIdModel Orders for one fund or share class.
sideBuy or Sell.
statusesOne or more order statuses.
referenceId, externalIdLook a Model Order up by your identifier or Monark's.

Note: The list endpoint returns each Model Order without its per-account orders: orders is an empty array, which does not mean the Model Order has no accounts. Retrieve a single Model Order by id to get the account breakdown.

Note: The lines you add to a draft are not returned. Until the Model Order is processed, orders is empty on the detail endpoint too, and the amounts are null. receivedOrderCount shows how many lines have been added, in every status, so keep your own record of each batch. A Model Order rejected while processing also has no per-account orders.

GET /primary/v1/omnibus/model-order/{id}
UI elementSourceNotes
Model nameModelOrder.modelIdThe value you supplied.
FundFund.name for ModelOrder.omnibusFundId
Share classShareClass.symbol or ShareClass.series for ModelOrder.omnibusShareClassId
SideModelOrder.side
StatusModelOrder.statusUses the same lifecycle as individual orders, after Draft and Processing.
NotionalModelOrder.notionalAmountThe sum of the per-account amounts, for a Buy.
Filled / remainingModelOrder.filledNotionalAmount, ModelOrder.remainingNotionalAmountFor a Buy, these add up to notionalAmount less order fees. Each account's feeAmount and effectiveNotionalAmount are on GET /primary/v1/omnibus/order/{id}. For a Sell: filledQuantity, remainingQuantity.
AccountsCount of ModelOrder.orders, or ModelOrder.receivedOrderCount before it is processedorders is returned by the detail endpoint only. receivedOrderCount is returned by both.
SubmittedModelOrder.submittedAtUtc
Account breakdownorders[].accountId, orders[].externalAccountNumber, orders[].notionalAmount, orders[].statusResolve account names as described in Accounts & Eligibility.
Rejection reasonModelOrder.statusReasonCode, ModelOrder.rejectedStatusReasonMessageModelOrder.rejectedOrderReferenceId is the line that caused the rejection, when there is one.

Model Orders raise their own webhook events, which mirror the individual order events: OmnibusModelOrderCreated, OmnibusModelOrderAccepted, OmnibusModelOrderRejected, OmnibusModelOrderSent, OmnibusModelOrderSettled, OmnibusModelOrderFailed, OmnibusModelOrderCancelled, and OmnibusModelOrderCancelRejected. OmnibusModelOrderPartiallyFilled is retired and never sent. Fills in the netting queue don't send an event of their own: read the block's progress (filledNotionalAmount, remainingNotionalAmount and so on) with GET /primary/v1/omnibus/model-order/{id}, and each account's fills with GET /primary/v1/omnibus/order/{id}. A block that fills completely in the netting queue moves to Settled without an event. The per-account orders do not raise OmnibusOrder events of their own, so track them through the Model Order events. The exception is a netting Model Order that reaches its nettingTif deadline: each per-account order then also sends OmnibusOrderSettled or OmnibusOrderCancelled. See Webhooks.

Fills

Every order in a Model Order is filled at the same NAV. When the transfer agent confirms the Model Order, the confirmed amount is allocated to each account's order pro rata to its amount, and every order moves to Settled together. If a fund prorates an oversubscribed repurchase offer, every account's sell fills by the same percentage and ends Settled, with the unfilled shares in remainingQuantity. Each Buy creates a tax lot in the account's position, and each Sell relieves lots according to the taxLotElection.

A Model Order routed to the netting queue nets as one order. Each fill is priced at that netting session's NAV (that day's NAV for a daily-NAV fund, or the last published NAV for a monthly-NAV fund) and split across the per-account orders pro rata to their remaining balances, so every account gets the same price on each fill. A block can fill over several sessions, and each fill creates its own tax lot. Any part that is not netted follows the Model Order's unnettedOrderRoute: it goes to the transfer agent at Monark's cutoff, or is cancelled at the netting deadline.

Each per-account order is also an order in its own right. It is returned by GET /primary/v1/omnibus/order with modelOrderId and modelId populated, so it appears in the account's own order history alongside orders placed individually. It can't be cancelled or changed on its own. See Portfolio & Positions.

Cancel a Model Order

POST /primary/v1/omnibus/model-order/cancel
{
  "modelOrderId": "8a4c2e60-0000-4000-8000-0000000000a1"
}

You can cancel a Model Order until Monark's cutoff, before it is sent to the transfer agent. Cancellation applies to every order within it. Once the Model Order is Executed, cancellation is refused with 409 (OrderNotCancellable). As with individual orders, cancellation is an asynchronous request: the response status is Accepted, Pending, or Rejected. Wait for the OmnibusModelOrderCancelled event, or retrieve the Model Order again, to confirm that it shows Cancelled. A Model Order routed to the netting queue can't be cancelled once submitted, and is refused with 409 (OrderNettingCancellationUnsupported).

A Draft is cancelled straight away: the response status is Accepted, and OmnibusModelOrderCancelled is sent. A Model Order that is Processing can't be cancelled (409, OrderNotCancellable). Wait for its outcome, then cancel it if it is Received.

To do thisDo this
Withdraw the whole allocationCancel the Model Order.
Add accounts to a draftSend another batch to investor-orders before you complete it.
Change amounts, or remove accountsCancel the Model Order, then submit a new one with the same modelId. Lines can't be changed or removed, even in a draft.
Cancel one account's orderNot supported through the individual order endpoints. Cancel and resubmit the Model Order without that account.

Handling errors

Refusals from investor-orders leave the Model Order in Draft and add nothing from the batch. The same checks run again for every line after complete. A failure then rejects the whole Model Order with the same statusReasonCode, sent in OmnibusModelOrderRejected.

HTTPstatusReasonCodeCauseWhat to do
409RequiredOrderActionsIncompleteAt least one account has outstanding requirements for the advisor sent on its order.Run the batch evaluation again with the same advisors, and complete what is Required.
400FinancialInstitutionFundAccessDeniedThe custodian is not enabled for the fund. Nothing is stored.Contact Monark.
400InvestorFinancialInstitutionMismatch, FinancialAdvisorInvalidAn account's owner or advisor is at a different custodian from the Model Order.Move the account to the right Model Order, or correct the advisor.
400AccountInvalidAn account cannot trade - for example, an entity account with no active individual.Fix or remove the account, and resubmit.
403AccountAccreditationInvalidAn account's accreditation is missing, more than 12 months old, or NOT_APPLICABLE.Update the accreditation, or remove the account.
409AccountInvalidAn account is closed.Remove the account, and resubmit.
409DuplicateReferenceIdThe Model Order referenceId has already been used.Retrieve the original by referenceId instead of resubmitting.
409DuplicateOrderReferenceIdAn order line's referenceId has already been used. A duplicate within the same request returns 400.Use new line references.
409MaxOrderNotionalExceeded, MaxDailyNotionalExceeded, MaxOrderQuantityExceeded, MaxDailyQuantityExceededThe Model Order exceeds a custodian's per-order or daily limit. Nothing is stored.Split the allocation, or contact Monark.
409OrderNettingCapabilityMissingThe Model Order was routed to the netting queue, but netting isn't enabled for this custodian, fund, and share class. Nothing is stored.Resubmit with routeInstruction: TransferAgent, or contact Monark.
400InvalidNettingInstructionsThe netting deadline can't be set, for example a nettingTifDate in the past. Nothing is stored.Choose a different nettingTif or date.
409InsufficientSellableShares, SellHoldingsUnavailableA Sell line exceeds the account's sellable shares, or holdings couldn't be verified.Correct the quantity, or retry later.
409OmnibusAccountNotFoundThere is no omnibus account for the custodian, share class and distribution election. Returned when you create the draft.Contact Monark.
400InvestorFinancialInstitutionMissingAn account's owner has no custodian.Fix or remove the account, and resubmit.
400InvalidOrderAmountA Buy line has no notionalAmount or has a quantity, or a Sell line the reverse.Correct the line.
400BelowMinimumInvestment, MinimumInvestmentHoldingsUnavailableA Buy line is below the share class's initial minimum for an account with no position in it, or Monark couldn't check for a position.Raise the amount or remove the account, or retry later.
400OrdersExceededThe Model Order would have more than 10,000 lines.Split the allocation into several Model Orders.
409DuplicateAccountIdThe account was added in an earlier batch. A duplicate within one batch returns 400.Leave the account out of the batch.
409ModelOrderNotDraftLines were added to, or complete was called for, a Model Order that is no longer Draft.Retrieve the Model Order. It may already be completed, or cancelled.
409OrderCountMismatchtotalOrderCount doesn't match the lines received. The Model Order stays Draft.Compare with receivedOrderCount, add any missing batch, and complete again.
409ModelOrderModifiedConcurrentlyAnother request changed the draft at the same time.Retrieve the Model Order and retry. Send batches one at a time.
400-Validation failed. The body is a validation problem whose errors map lists the messages for each field.Correct and resubmit.

When you resubmit after a rejection, use new referenceId values, because reference IDs must be unique per partner.

Next steps


Did this page help you?