Skip to main content
Every account, real or paper, places and manages orders through the same host operations. This guide covers what to check before you submit, how to submit each order type, how to follow an order to its final state, and how to recover when you cannot tell whether a command took effect. The examples use a BTC/USDT perpetual and the host ID bybit. Discover the hosts and markets available to you with List hosts and List host markets, and find an account’s host with Get an account.

Before you submit

An order is valid only if it fits the host market’s order rules. Plurex checks your order against exactly the rules it publishes and never rounds your values, so read them first.
1

Find the host market

Call List host markets with the account’s hostId and filters such as base, quote and types. Order rules come from the host market, never from the venue market. A market the host does not list cannot be traded on that host.
2

Check the order type

orderTypes.limit is always present. market, triggerLimit and triggerMarket are null when the market does not support that type; submitting one anyway returns 422 NotSupported.
3

Fit price and size to the rules

Prices are whole multiples of price.increment, sizes are whole multiples of size.increment and at least size.min, and a priced order’s value must reach value.min. Sizes are in native contracts, so read contractDetails before converting an amount of money into a size. An order that breaks a rule returns 422 Rejected.
4

Check the options you send

tif must be in options.supportedTimeInForce. Send postOnly: true, reduceOnly: true or a non-null positionEffect only when the matching supportsPostOnly, supportsReduceOnly or supportsPositionEffect flag is true.
5

Check clientOrderId support

Send a clientOrderId only when the host’s capabilities.orders.submitOrder.clientOrderId is supported. To recover from an unclear submission you also need getOrder.byClientOrderId or getOrder.byClientOrderIdForInstrument.
This is the limit-order entry of a perpetual market (example values; read the live ones from the market):
Order rules explains every rule, including the value calculation for inverse markets and how to round in the right direction.
Choose a clientOrderId that is unique per order, so a lookup by it finds exactly one order. Plurex does not publish length or character rules for it; a short value of letters, digits and hyphens is the safest choice.

Submit an order

Submit an order takes the accountId and one order, whose type is Limit, Market, TriggerLimit or TriggerMarket. Every order has an instrument, a side (Buy or Sell) and reduceOnly. There is no leverage field on an order: leverage is a market setting (see Balances, positions and settings).

Limit order

A limit order needs size, price and tif. postOnly defaults to false.

Market order by size or by notional

A market order carries sizing instead of size and price. Size is in native contracts; Notional is an amount of the quote asset. Each side lists the units it accepts in orderTypes.market.sizingSupport.buy and .sell. tif defaults to IOC and must still be in the market’s supportedTimeInForce.
To spend a fixed amount of quote, size by notional where the side supports it:
A notional is not a size promise: the size you receive is the notional divided by the fill price, and can fall below the market’s minimum size. When notional.increment is null the host may round the amount itself; the returned order’s sizing shows what it accepted when the host reports it.

Trigger orders

TriggerLimit and TriggerMarket wait until the reference price meets the trigger condition, then place a limit or market order. Read the market’s trigger entry first:
  • trigger.price follows trigger.price.increment.
  • condition is RefPriceGTE (the reference is at or above the price) or RefPriceLTE (at or below it), and must be listed in buyConditions or sellConditions for your side. Choose a trigger price on the far side of the current reference: if the condition is already met when you submit, what happens is up to the host.
  • When referencePrice is UserSelectable, send a reference from its prices list. When it is HostSelected, the host fixes the reference: omit reference.
A trigger limit buy that enters on a breakout:
A stop-loss for a long position is a trigger market sell with reduceOnly: true, so it can only shrink the position:

What the response means

A successful response is the order as the host accepted it:
Keep id: every later lookup and cancel can use it. The order records what the host reports. Submitted options (tif, postOnly, reduceOnly, positionEffect) are not echoed, and averagePrice and realizedPnl are null when the host does not report them. Plurex does not calculate an average price from fills.

Order states

An order is in one of four states. Live is the only one that can change. There is no separate partly-filled state and no updatedAt. Compare sizeTraded with the order’s size to see progress.

Track orders

Look up by client order ID:
Where the host supports only the instrument-scoped variant, use ByClientOrderIdForInstrument:
Read several orders at once with GetOrders. Because unknown identifiers are omitted, compare the result with what you asked for:
The list operations are paged: omit cursor for the first page, then send each nextCursor back with the same query until it is null. Each variant’s capability entry gives its defaultOrdering. Every list operation, and each of its variants, is optional, so check listOpenOrders, listClosedOrders and fills.listFills in the host’s capabilities first. A fill gives the price, size, fees and, when the host reports them, its execution id and role (Maker or Taker). Its side is your order’s side, not the taker’s.

Cancel orders

Cancel one order

Cancel an order accepts ById on every host, plus ByClientOrderId and ByClientOrderIdForInstrument where cancelOrder capabilities say so:
A success is an empty acknowledgement, {}. It means the host accepted the cancel, not that the order is closed: some hosts cancel asynchronously, and the order can fill before the cancel lands. Confirm the final state with Get an order or the order stream. Cancelling is safe to repeat.

Cancel several orders

Cancel orders takes a list of IDs or client order IDs and returns one result per identifier, so it can partly succeed:
Check every result. A Failed result carries the code a single cancel would have returned, with the same meaning. RateLimited, Unavailable, UpstreamTimeout and UpstreamFailure are transient, so retry those identifiers. Rejected and NotSupported mean the request must change. Errors that stop the whole batch, such as a missing account, come back as an ordinary error response.

Cancel everything

Cancel all orders cancels every open order on the account (Global) or on one instrument (ByInstrument):
Success means no matching orders remain open; orders that were already gone or closed count as cancelled. Any other failure returns 502 CancelAllFailed, after which List open orders shows what is still open. It is safe to repeat.

Handle an unclear outcome

A timeout, a dropped connection or a 5xx response from SubmitOrder does not tell you whether the order was placed. Submitting again may place a second order. A 4xx response means the request needs to change; on its own it does not prove the order was never placed (see Errors).
  1. Always send a clientOrderId when the host supports it. Without one, you can only search ListOpenOrders and ListClosedOrders for an order that matches.
  2. Look the order up with GetOrder ByClientOrderId, or ByClientOrderIdForInstrument if that is the variant the host supports.
  3. If the order is found, it was placed. Track it; do not resubmit.
  4. 404 OrderNotFound is not proof that the order was never placed: the host may not show it yet. Retry the lookup a few times with a growing delay, and if you are connected to the order stream, watch for an event whose order carries your client order ID.
  5. Resubmit only when you are satisfied the order does not exist. 409 DuplicateClientOrderId means an open order already holds that client order ID: look it up and track it. Reusing the client order ID of an order that has already filled or been cancelled may place a new order, so do not rely on 409 to catch duplicates. Use a unique clientOrderId for every order you intend to place, and always complete the lookup before you resubmit.

Cancel an order whose ID you never received

If you no longer want the order, you do not need its ID. Where cancelOrder.byClientOrderId or cancelOrder.byClientOrderIdForInstrument is supported, cancel by client order ID:
Read the result the same way as any cancel. OrderAlreadyClosed means the order existed and finished, possibly filled, so do not resubmit it. OrderNotFound still leaves the question open; look the order up again before deciding.

Worked example

This flow places a limit order on a paper or real account, confirms it, cancels it and checks the result. It assumes PLUREX_API_KEY, PLUREX_API_SECRET and PLUREX_ACCOUNT_ID are set.
1

Read the market's order rules

Use the hostId of the account you trade (from Get an account); for a paper account that is the paper host, not the real one. Take orderTypes.limit from the BTC-USDT-PERP market and check the price and size you plan to send against it.
2

Submit with a client order ID

If this call times out, go straight to the next step: it tells you whether the order exists.
3

Confirm the order

4

Cancel it

5

Confirm the final state

Repeat the GetOrder call until state is no longer Live. Expect Cancelled, or Filled if the order filled before the cancel took effect.