Webhooks
How to receive and act on Omnibus webhook events: setup, what each event means for your platform, who receives it, and recovering missed events.
Register one HTTPS endpoint and Monark posts an event for every Omnibus state change. This page covers how to handle them. Payloads for each event are in the API reference under Omnibus Webhooks, and signature verification code is on the Webhooks page in Getting Started.
Setup
- Register:
POST /primary/v1/webhookwith yoururland atoken. Monark signs each delivery with the token - Update or pause:
PUT /primary/v1/webhookreplaces the whole configuration, so sendurl,tokenandisActiveevery time. Leaving outisActivedeactivates the webhook, and events raised while it is inactive are not delivered - Handle repeats: use
X-Webhook-Event-Idto skip events you have already processed. Treat each event as a signal: re-read the order or position with aGETbefore acting
Omnibus Events
| Event | Sent when | What to do |
|---|---|---|
OmnibusOrderCreated | An order is created | Store Monark's id against your referenceId. If the order is PendingActions, prompt for the outstanding order actions |
OmnibusOrderAccepted | An order is accepted for execution. Status becomes PendingExecution | Show the order as accepted. It can still be cancelled or amended until Monark's cutoff, unless it is routed to the netting queue |
OmnibusOrderRejected | An order is rejected after submission, for example Settlement:TaRejected, or an Execution: code for a netting order before it is accepted. Orders rejected at submission come back in the 201 response instead | Show the statusReasonCode and message, and release any cash or shares you set aside |
OmnibusOrderSent | An order is sent to the TA. Status becomes Executed | Show the order as final: it can no longer be cancelled. Nothing more is filled until the TA confirms |
OmnibusOrderSettled | The TA confirms the order and tax lots are created, or a netting order with unnettedOrderRoute: Cancel reaches its deadline part-filled (Execution:Expired). Not sent when an order fills completely in the netting queue | Record fills and refresh positions. For a sell, check remainingQuantity in case the fund gated the redemption |
OmnibusOrderUpdated | An amendment is applied | Refresh the order |
OmnibusOrderUpdateRejected | An amendment accepted as Pending is refused | Show the reasonCode. The order keeps its previous terms |
OmnibusOrderCancelled | An order is cancelled, including a netting order with unnettedOrderRoute: Cancel that reaches its deadline with nothing filled (Execution:Expired) | Mark it cancelled and release any cash or shares you set aside |
OmnibusOrderCancelRejected | A cancellation accepted as Pending is refused | Show the reasonCode. The order continues |
OmnibusOrderFailed | Settlement fails for an operational reason, for example Settlement:ConfirmationTimeout | Show the order as failed and contact Monark Operations |
OmnibusModelOrderCreated, Accepted, Rejected, Sent, Settled, Cancelled, CancelRejected, Failed | The same milestones for a model order as a whole | Handle as above for the block. Its client lines send no OmnibusOrder events, except when a netting model order reaches its deadline, so read each one with GET /primary/v1/omnibus/order/{id} |
OmnibusOrderFundingInstruction | At Monark's cutoff, once per custodian, share class and election with buys. Lists your orders, their amounts net of any order fee, and wire instructions: MMM Securities' if the custodian is in the MMM Securities master omnibus, otherwise the TA's | Make sure the custodian wires the amount as instructed, by the wire deadline agreed with Monark. Reconcile orders[].amount to your buys |
OmnibusCancelOrderFundingInstruction | Reserved. Not currently sent | — |
OmnibusDividendCreated | A distribution is allocated to a client's lot. One event per lot | Sum by accountId for each client's total, and refresh positions for DRIP elections |
OmnibusOrderPartiallyFilled, OmnibusModelOrderPartiallyFilled | Retired and never sent. Fills in the netting queue don't send an event of their own, and an order that fills completely there moves to Settled without one | Read fills, and the order's status, with GET /primary/v1/omnibus/order/{id} or GET /primary/v1/omnibus/model-order/{id} |
FinancialInstitution, FinancialInstitutionUpdate | A custodian is added or changed | Refresh your list of custodians |
A rejection or refusal returned directly in an API response does not also send a webhook. Handle it from the response.
Completing a model order is the exception. POST /primary/v1/omnibus/model-order/complete returns 202 with a status of Processing, and the outcome follows as OmnibusModelOrderCreated, or as OmnibusModelOrderRejected or OmnibusModelOrderFailed with a statusReasonCode. A draft model order that is cancelled, by you or overnight with DraftExpired, sends OmnibusModelOrderCancelled. Batches refused by investor-orders send nothing.
Delivery & Replay
Each delivery is an HTTPS POST with a JSON body of { "eventType": "...", "data": { ... } }. Fields are camelCase and enums are strings. The body has no timestamp of its own.
- Headers:
X-Webhook-Event-Ididentifies the event,X-Webhook-Signaturecarries the signature andUser-AgentisMonarkWebhookClient - Signature: Base64 of an HMAC-SHA256 of the raw UTF-8 request body, keyed with your
tokenas UTF-8. Compute it over the body exactly as received, before parsing, and reject any delivery that doesn't match. See Webhooks for sample code - Retries: Monark picks up new events within about a minute. A delivery that times out after 30 seconds, returns
408or a5xx, or hits a network error is retried twice, after 1 and 5 seconds. It is then markedFailedand not sent again. Other responses are not retried - Order: events can arrive out of order, so rely on the record's current state from a
GET - Event log:
GET /primary/v1/webhook/{id}/eventslists past events with theireventType,data,createdAt,deliveredAtand adeliveryStatusofPending,DeliveredorFailed.fromandtoare required;eventTypeanddeliveryStatusfilter further. Failed deliveries can't be resent, so check the log after any outage on your side and re-read the affected records
Updated 27 days ago