Skip to main content
POST
/
api
/
accounts
/
{accountId}
/
router
/
orders
curl --request POST \
  --url https://trade.predexon.com/api/accounts/{accountId}/router/orders \
  --header 'Content-Type: application/json' \
  --header 'x-api-key: <api-key>' \
  --data '
{
  "predexonId": "px-uvtpjis2k7bj",
  "side": "buy",
  "amount": "10.00"
}
'
{
  "routerOrderId": "rord-6f2e4c1a-83d8-4c9b-8b3f-d4a9c1e5c2b1",
  "predexonId": "px-uvtpjis2k7bj",
  "side": "buy",
  "type": "market",
  "requestedAmount": "10",
  "requestedSize": null,
  "fills": [
    {
      "venue": "polymarket",
      "orderId": "0x9a3f...",
      "status": "filled",
      "size": "18.115000",
      "price": "0.331200",
      "amount": "6.000000"
    },
    {
      "venue": "predict",
      "orderId": "0xa1c2...",
      "status": "filled",
      "size": "11.820000",
      "price": "0.342000",
      "amount": "4.000000"
    }
  ],
  "summary": {
    "totalSize": "29.935000",
    "totalAmount": "10.000000",
    "avgPrice": "0.335070",
    "venuesUsed": 2,
    "venuesFailed": 0
  },
  "_routing": {
    "considered": [
      {
        "venue": "polymarket",
        "avgPrice": "0.331200",
        "topLevelPrice": "0.330000",
        "droppedReason": null,
        "feeBpsAtTop": 35
      },
      {
        "venue": "predict",
        "avgPrice": "0.342000",
        "topLevelPrice": "0.340000",
        "droppedReason": null,
        "feeBpsAtTop": 30
      },
      {
        "venue": "opinion",
        "avgPrice": null,
        "topLevelPrice": "0.350000",
        "droppedReason": "zero_depth",
        "feeBpsAtTop": 20
      }
    ],
    "reasoning": "Routed to polymarket and predict by best effective price. Skipped opinion (no depth on the relevant side)."
  }
}

Overview

Place a market order that the router splits across every routed venue offering the outcome identified by predexonId. Returns per-venue fills, an aggregate summary, and the routing decision. The router:
  1. Expands predexonId to the cross-venue equivalence set.
  2. Filters to venues the account has enabled, intersects with those the router is actively streaming.
  3. For buys — fans out balance reads and aborts if aggregate balance is below the requested notional. For sells — fans out position reads to cap each venue’s allocation by available size.
  4. Walks the merged fee-inclusive order books from best to worst effective price and computes a per-venue split.
  5. Dispatches per-venue orders in parallel.
  6. Collects every dispatch result (success or failure) and returns a unified response.
There is no cross-venue atomicity. One venue may fill while another fails, and both outcomes surface in fills[]. A 201 Created response may still contain per-venue failures — check summary.venuesFailed. See the Order Router concept page for an end-to-end explanation of how routing and splitting work.

Path Parameters

ParamTypeDescription
accountIdstringTrading account ID. Must belong to the calling API key. See the Trading API accounts docs for how to create and fund one.

Request Body

FieldTypeRequiredDescription
predexonIdstringYesCanonical predexon_id for the outcome. The router expands it to every routed venue listing for that outcome.
sidestringYesbuy or sell.
amountstringRequired on buyUSD/stablecoin notional to spend. Positive decimal string. Must not be set on sell.
sizestringRequired on sellNumber of shares to sell. Positive decimal string. Must not be set on buy.

Response Fields

Top level

FieldTypeDescription
routerOrderIdstringUnique identifier for this routed order (prefix rord-).
predexonIdstringEchoes the request predexonId.
sidestringbuy or sell.
typestringAlways "market".
errorCodestring?Present only on a 502 response when every dispatched venue failed. Set to "all_venues_failed". Absent on a 201.
requestedAmountstring?Echo of the request amount. Present on buy orders; null on sell orders.
requestedSizestring?Echo of the request size. Present on sell orders; null on buy orders.
fills[]arrayOne entry per dispatched venue.
summaryobjectAggregate fill summary.
_routingobjectRouting decision transparency — see below.
Request correlation uses the x-request-id response header — the router echoes the header on every response. There is no _trace block in the body.

Fill entry

size, price, and amount are normalised to 6-decimal strings across every venue — partners parsing fills get consistent formatting regardless of which venue produced the fill.
FieldTypeDescription
venuestringpolymarket, predict, opinion, or limitless.
orderIdstringVenue-native order identifier. Use this when reconciling with the venue directly.
statusstringfilled, partial, open, cancelled, or failed.
sizestringShares matched on this venue.
pricestringVolume-weighted average fill price on this venue.
amountstringNotional (stablecoin) matched on this venue.
feeobject?Venue-native fee data, passed through verbatim from the venue. Absent when the venue does not report one. Shape varies by venue.
errorstring?Present only when status is failed.

Summary

FieldTypeDescription
totalSizestringAggregate shares matched across all venues.
totalAmountstringAggregate notional matched across all venues.
avgPricestringVolume-weighted average fill price across all venues.
venuesUsedintNumber of venues that successfully produced a fill (filled, partial, or open).
venuesFailedintNumber of venues whose dispatch failed. A 201 can still have venuesFailed > 0.

_routing

Transparency block describing how the router made its allocation decision.
FieldTypeDescription
considered[]arrayVenues the router evaluated and could reasonably have routed to. Infrastructure dropouts (missing or disconnected books) are excluded. Read fills[] for what happened — considered[] records the decision set.
considered[].venuestring
considered[].avgPricestring?Projected volume-weighted price on this venue. null if no projected fill.
considered[].topLevelPricestring?Top-of-book price on the relevant side.
considered[].droppedReasonstring?Reason this venue received no allocation. Known values are zero_depth (no depth on the relevant side) and no_position (sell-side only — account holds nothing to sell on this venue). null when the venue was allocated a share. The enum is open-ended; new reasons may be added over time, so treat unknown values as informational.
considered[].feeBpsAtTopnumberEffective venue fee at the top of book in basis points. May be fractional (e.g. 24.6975).
reasoningstringNatural-language explanation of the routing decision.

Status Codes & Errors

HTTP status is binary: 201 when at least one venue produced a fill, 502 when no venue filled. Partial vs. full success is a body-level distinction — read summary.venuesFailed.
  • summary.venuesFailed === 0full success. Every dispatched venue filled.
  • summary.venuesFailed > 0 with status 201partial success. Some venues filled, others failed. Inspect per-fill status and fills[].error to see which.
Every non-201 response carries a machine-readable errorCode alongside the human-readable error. On 502 all_venues_failed, the response is the full Place Order body (with fills[] and _routing) plus errorCode — diagnose per-venue failures from fills[].error and _routing.considered[].
StatuserrorCodeMeaning
201(absent)At least one venue produced a fill. Full success when summary.venuesFailed === 0; partial success when > 0.
400parse_errorMissing or invalid request body field.
400insufficient_balanceAggregate balance across enabled venues is below the requested notional (market buy only).
404predexon_not_routableNo routed venue carries the supplied predexonId.
502no_allocationsNo venue had sufficient liquidity to allocate any portion of the order.
502all_venues_failedEvery dispatched venue failed. Response includes the full Place Order body for diagnosis.
503registry_unavailableRouting registry is temporarily unavailable. Retry with exponential back-off.

Examples

Full success — market buy by notional

Both dispatched venues filled. summary.venuesFailed is 0. Request:
{
  "predexonId": "px-uvtpjis2k7bj",
  "side": "buy",
  "amount": "10.00"
}
Response (201):
{
  "routerOrderId": "rord-6f2e4c1a-83d8-4c9b-8b3f-d4a9c1e5c2b1",
  "predexonId": "px-uvtpjis2k7bj",
  "side": "buy",
  "type": "market",
  "requestedAmount": "10",
  "requestedSize": null,
  "fills": [
    {
      "venue": "polymarket",
      "orderId": "0x9a3f...",
      "status": "filled",
      "size": "18.115000",
      "price": "0.331200",
      "amount": "6.000000"
    },
    {
      "venue": "predict",
      "orderId": "0xa1c2...",
      "status": "filled",
      "size": "11.820000",
      "price": "0.342000",
      "amount": "4.000000"
    }
  ],
  "summary": {
    "totalSize": "29.935000",
    "totalAmount": "10.000000",
    "avgPrice": "0.335070",
    "venuesUsed": 2,
    "venuesFailed": 0
  },
  "_routing": {
    "considered": [
      {
        "venue": "polymarket",
        "avgPrice": "0.331200",
        "topLevelPrice": "0.330000",
        "droppedReason": null,
        "feeBpsAtTop": 35
      },
      {
        "venue": "predict",
        "avgPrice": "0.342000",
        "topLevelPrice": "0.340000",
        "droppedReason": null,
        "feeBpsAtTop": 30
      },
      {
        "venue": "opinion",
        "avgPrice": null,
        "topLevelPrice": "0.350000",
        "droppedReason": "zero_depth",
        "feeBpsAtTop": 20
      }
    ],
    "reasoning": "Routed to polymarket and predict by best effective price. Skipped opinion (no depth on the relevant side)."
  }
}
The x-request-id response header carries a request correlation identifier — propagate it when reporting issues so support can correlate your call with router-side logs.

Market sell by size

{
  "predexonId": "px-uvtpjis2k7bj",
  "side": "sell",
  "size": "20"
}
The router fans out position reads to each enabled venue, caps each venue’s allocation by the user’s position size there, and walks the merged bid-side book from best price down.

Partial success — still a 201

At least one venue filled, so the response is still 201. summary.venuesFailed is 1, and the failed venue returns an error string for diagnostics. errorCode is absent at the top level because at least one venue filled.
{
  "fills": [
    { "venue": "polymarket", "orderId": "0x9a3f...", "status": "filled", "size": "18.115000", "price": "0.331200", "amount": "6.000000" },
    { "venue": "predict",    "orderId": "failed-...", "status": "failed", "size": "0.000000", "price": "0.000000", "amount": "0.000000", "error": "Plane returned HTTP 502" }
  ],
  "summary": {
    "totalSize": "18.115000",
    "totalAmount": "6.000000",
    "avgPrice": "0.331200",
    "venuesUsed": 1,
    "venuesFailed": 1
  }
}

All venues failed (502)

A 502 with the full Place Order body. Use fills[].error to diagnose per-venue failures.
{
  "routerOrderId": "rord-a1b2...",
  "predexonId": "px-uvtpjis2k7bj",
  "side": "buy",
  "type": "market",
  "errorCode": "all_venues_failed",
  "requestedAmount": "10",
  "requestedSize": null,
  "fills": [
    {
      "venue": "polymarket",
      "orderId": "failed-...",
      "status": "failed",
      "size": "0.000000",
      "price": "0.000000",
      "amount": "0.000000",
      "error": "Plane returned HTTP 502"
    }
  ],
  "summary": {
    "totalSize": "0.000000",
    "totalAmount": "0.000000",
    "avgPrice": "0",
    "venuesUsed": 0,
    "venuesFailed": 1
  },
  "_routing": { "considered": [], "reasoning": "All eligible venues failed." }
}
The router serializes concurrent requests per account to narrow (but not eliminate) the self-induced double-spend window on market buys. If two requests race from different machines, per-venue balance checks at the exec plane are the authoritative guard. Partners should still size concurrent order flow against aggregate balance.

Authorizations

x-api-key
string
header
required

Trading key provided by Predexon. The data key used by the Sports Discovery API on api.predexon.com is a separate credential.

Path Parameters

accountId
string
required

Account ID. Must belong to the calling API key.

Body

application/json
predexonId
string
required

Canonical predexon_id for the outcome. The router expands to every routed venue listing for that canonical outcome.

side
enum<string>
required
Available options:
buy,
sell
amount
string

USD/stablecoin notional to spend. Required when side is buy. Must not be set when side is sell. Must be a positive decimal string.

size
string

Number of shares to sell. Required when side is sell. Must not be set when side is buy. Must be a positive decimal string.

Response

At least one venue produced a fill. Full success when summary.venuesFailed === 0; partial success when > 0 — some venues filled, others failed, inspect per-fill status and fills[].error to see which.

routerOrderId
string
required

Unique identifier for this routed order (prefix rord-).

predexonId
string
required

Echoes the request predexonId.

side
enum<string>
required
Available options:
buy,
sell
type
enum<string>
required
Available options:
market
requestedAmount
string | null
required

Echo of the request amount. Present (as a stringified number) on buy orders; null on sell orders.

requestedSize
string | null
required

Echo of the request size. Present (as a stringified number) on sell orders; null on buy orders.

fills
object[]
required

One entry per venue that was dispatched. A single order can produce multiple fills. size, price, and amount are normalised to 6-decimal strings across every venue.

summary
object
required
_routing
object
required

Transparency block describing how the router made its allocation decision.

errorCode
enum<string>

Present only on a 502 response when every dispatched venue failed. Set to "all_venues_failed". Absent on a 201 success.

Available options:
all_venues_failed