POST /v1/orders
accepts per-share price guards on market orders so you can bound the price you
actually fill at. This page explains how to read those prices and which guards
to set on each venue.
Units: one scale across every venue
ParlayX normalizes units so you work with the same scale no matter which venue a market lives on:
Size every order with exactly one of
amount or shares (supplying
both, or neither, is rejected):
amount(USDC) works for any order. ParlayX converts it to each venue’s native representation when it routes your order.shares(outcome contracts) is supported on sells and limit orders only — a market BUY is sized in USDC notional by the venue, so it must useamount.
Per-outcome prices: bid, mid, and ask
GET /v1/markets/{marketVenue}/{marketId} and GET /v1/markets/match
return a MarketOutcome for each side of the market, with indicative prices
expressed as implied probability (0–1). The single-market endpoint returns
the full bid / mid / ask; match returns mid only, so read prices
from the single-market endpoint when you need bid/ask to set guards:
Example response fragment:
ask − bid) is your worst-case round-trip cost. Wider spreads
mean less liquidity — size your per-share guard accordingly.
bid, mid, and ask are indicative snapshots from the venue at read
time. They are not a quote and do not guarantee a fill at that price —
use them to set the per-share guards described below.Controlling fill price on a market order
Market orders ("type": "market") submitted through POST /v1/orders
accept per-share guards that cap how badly your fill can slip from the price
you saw when you decided to trade. The exact field depends on the venue. To
rest at a fixed price instead, submit a limit order ("type": "limit") with
a limitPrice.
Polymarket market orders
Polymarket market orders accept both FOK (fill-or-kill) and FAK (fill-and-kill, partial allowed) and expose two optional per-share guards:maxFillPrice— per-share cap for a BUY. Fills come back at or below it. If omitted, the buy is bounded only byamount(no per-share cap).minFillPrice— per-share floor for a SELL. Fills come back at or above it. If omitted, a default slippage floor (currently 2% below the prevailing midpoint) is applied.
(0, 1). Use ask to
set a tight buy cap, and bid to set a tight sell floor:
maxFillPrice = ask + tolerance on a BUY (or minFillPrice = bid − tolerance on a SELL)
where tolerance is your acceptable slippage budget.
Limitless market orders
Limitless market orders are FAK (fill-and-kill, partial allowed) and work for both BUY and SELL. They take the same optional per-share guards as Polymarket:maxFillPrice caps a BUY, minFillPrice floors a SELL. The
difference is the default: when you omit the guard, the executor reads the
live quote and applies a 50bps headroom (ask × 1.005 for a BUY,
bid × 0.995 for a SELL) rather than leaving the order uncapped. For a
resting order with an explicit bound, submit a limit order
(timeInForce: { "type": "GTC" } or { "type": "GTD" }) with a limitPrice.
A "GTD" order carries its expiresAt (ISO-8601, UTC) inside the
timeInForce object, after which the venue auto-cancels it.
Every Limitless order requires the
marketId — the same value the
Markets API returns — in addition to outcomeId. Omitting it fails the
request with a 400 invalidRequest.Choosing prices in practice
- Call
GET /v1/markets/{marketVenue}/{marketId}and readbid,mid,askon the outcome you want to trade. - Decide your slippage tolerance — e.g. 2 cents per share.
- Submit the order with the venue-appropriate guard:
- BUY →
maxFillPrice = ask + tolerance - SELL →
minFillPrice = bid − tolerance - On Limitless, omitting the guard is also fine: the executor derives one from the live quote with a 50bps headroom.
- BUY →
- Inspect the resulting fill via
GET /v1/orders/{orderId}. Each market order reportsfilledAmountand theaveragePriceso you can reconcile against the guard you set.
PRICE_EXCEEDED error code on the market order rather than partially filling
at a worse price.
Stop orders (conditional)
A stop ("type": "stop") is a market order plus a price trigger. Nothing
rests on the venue while it waits: ParlayX watches the market’s top of book and,
when the reference price crosses your triggerPrice, fires a market child
order for you. It is certain to fire once the level is crossed, but — like any
market order — the fill price is not guaranteed.
The watch direction comes from side, so there is no separate direction field:
Two parameters govern the trigger:
triggerPrice— the level (0–1 implied probability) the reference must cross.triggerFillDepth(optional, default1) — the cumulative resting size (in outcome shares) that must sit past the level before firing. The default fires on touch; a larger value waits for that much fillable depth, filtering a thin quote that pokes through the level on negligible size.
FOK/FAK,
Limitless FAK). If the market gaps straight through the level, the child still
fills at the next available price (a thin book may partially fill at the default
depth).
orderId. The response is the same { "orderId": "..." } as any submission; that id is the
only handle you need for Get Order and
Cancel Order. Reading it back returns an
order whose single marketOrders entry is type: "stop", carrying
conditionalStatus; once it fires, the order it places is rolled up onto that
entry (status/filledAmount/averagePrice), so there is no second id to chase
— see Conditional orders for the full
shape. Cancelling before the trigger fires removes the watch and rests
nothing; after it fires, cancelling the same orderId cancels the order it
placed.
Stop-limit orders (conditional)
A stop-limit ("type": "stop_limit") shares the exact trigger of a stop, but
fires a limit child that rests at a price you set rather than a market child.
The trigger — reference side, cross direction, triggerPrice, triggerFillDepth
— is identical to a stop (see the table above); the difference is what happens on
activation:
- A stop fires a market child: certain to fill once the level is crossed, but at whatever price the book offers.
- A stop-limit fires a limit child that rests at your
limitPrice: the fill price is guaranteed, but the fill itself is not — if the market gaps past your limit, the child rests unfilled until the price comes back (or you cancel it).
limitPrice (0–1 implied probability) — the price the fired limit order rests
at. Its time-in-force is the resting limit set, GTC or GTD, on both
venues (a fill-and-kill child would defeat the point of a resting limit).
marketOrders entry of type: "stop_limit", carrying
conditionalStatus; once fired, the resting limit it places is rolled up onto
that entry — so its status can sit partial/open until the limit fills,
under the one orderId you already hold. A GTD child’s expiresAt is fixed at
submit time but the child only rests once the trigger fires, so a GTD whose
expiry has already passed by fire time is rejected by the venue; prefer GTC (or
a generous expiry) for triggers that may sit armed for a while. Cancellation
works as for a stop: before the trigger the watch is removed; after, cancelling
the same orderId cancels the resting limit it placed.