> ## Documentation Index
> Fetch the complete documentation index at: https://enterprise.predexon.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Place Market Order

> Place a market order that the router splits across routed venues

## 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](/concepts/order-router) for an end-to-end explanation of how routing and splitting work.

## Path Parameters

| Param       | Type   | Description                                                                                                                                                                                |
| ----------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `accountId` | string | Trading account ID. Must belong to the calling API key. See the [Trading API accounts docs](https://docs.predexon.com/trading-api/accounts/create-account) for how to create and fund one. |

## Request Body

| Field        | Type   | Required           | Description                                                                                                    |
| ------------ | ------ | ------------------ | -------------------------------------------------------------------------------------------------------------- |
| `predexonId` | string | Yes                | Canonical `predexon_id` for the outcome. The router expands it to every routed venue listing for that outcome. |
| `side`       | string | Yes                | `buy` or `sell`.                                                                                               |
| `amount`     | string | Required on `buy`  | USD/stablecoin notional to spend. Positive decimal string. Must not be set on `sell`.                          |
| `size`       | string | Required on `sell` | Number of shares to sell. Positive decimal string. Must not be set on `buy`.                                   |

## Response Fields

### Top level

| Field             | Type    | Description                                                                                                       |
| ----------------- | ------- | ----------------------------------------------------------------------------------------------------------------- |
| `routerOrderId`   | string  | Unique identifier for this routed order (prefix `rord-`).                                                         |
| `predexonId`      | string  | Echoes the request `predexonId`.                                                                                  |
| `side`            | string  | `buy` or `sell`.                                                                                                  |
| `type`            | string  | Always `"market"`.                                                                                                |
| `errorCode`       | string? | Present only on a 502 response when every dispatched venue failed. Set to `"all_venues_failed"`. Absent on a 201. |
| `requestedAmount` | string? | Echo of the request `amount`. Present on buy orders; `null` on sell orders.                                       |
| `requestedSize`   | string? | Echo of the request `size`. Present on sell orders; `null` on buy orders.                                         |
| `fills[]`         | array   | One entry per dispatched venue.                                                                                   |
| `summary`         | object  | Aggregate fill summary.                                                                                           |
| `_routing`        | object  | Routing 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.

| Field     | Type    | Description                                                                                                                      |
| --------- | ------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `venue`   | string  | `polymarket`, `predict`, `opinion`, or `limitless`.                                                                              |
| `orderId` | string  | Venue-native order identifier. Use this when reconciling with the venue directly.                                                |
| `status`  | string  | `filled`, `partial`, `open`, `cancelled`, or `failed`.                                                                           |
| `size`    | string  | Shares matched on this venue.                                                                                                    |
| `price`   | string  | Volume-weighted average fill price on this venue.                                                                                |
| `amount`  | string  | Notional (stablecoin) matched on this venue.                                                                                     |
| `fee`     | object? | Venue-native fee data, passed through verbatim from the venue. Absent when the venue does not report one. Shape varies by venue. |
| `error`   | string? | Present only when `status` is `failed`.                                                                                          |

### Summary

| Field          | Type   | Description                                                                          |
| -------------- | ------ | ------------------------------------------------------------------------------------ |
| `totalSize`    | string | Aggregate shares matched across all venues.                                          |
| `totalAmount`  | string | Aggregate notional matched across all venues.                                        |
| `avgPrice`     | string | Volume-weighted average fill price across all venues.                                |
| `venuesUsed`   | int    | Number of venues that successfully produced a fill (`filled`, `partial`, or `open`). |
| `venuesFailed` | int    | Number of venues whose dispatch failed. A `201` can still have `venuesFailed > 0`.   |

### `_routing`

Transparency block describing how the router made its allocation decision.

| Field                        | Type    | Description                                                                                                                                                                                                                                                                                                                                  |
| ---------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `considered[]`               | array   | Venues 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[].venue`         | string  |                                                                                                                                                                                                                                                                                                                                              |
| `considered[].avgPrice`      | string? | Projected volume-weighted price on this venue. `null` if no projected fill.                                                                                                                                                                                                                                                                  |
| `considered[].topLevelPrice` | string? | Top-of-book price on the relevant side.                                                                                                                                                                                                                                                                                                      |
| `considered[].droppedReason` | string? | 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[].feeBpsAtTop`   | number  | Effective venue fee at the top of book in basis points. May be fractional (e.g. `24.6975`).                                                                                                                                                                                                                                                  |
| `reasoning`                  | string  | Natural-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 === 0` — **full success.** Every dispatched venue filled.
* `summary.venuesFailed > 0` with status `201` — **partial 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[]`.

| Status | `errorCode`             | Meaning                                                                                                         |
| ------ | ----------------------- | --------------------------------------------------------------------------------------------------------------- |
| `201`  | *(absent)*              | At least one venue produced a fill. Full success when `summary.venuesFailed === 0`; partial success when `> 0`. |
| `400`  | `parse_error`           | Missing or invalid request body field.                                                                          |
| `400`  | `insufficient_balance`  | Aggregate balance across enabled venues is below the requested notional (market buy only).                      |
| `404`  | `predexon_not_routable` | No routed venue carries the supplied `predexonId`.                                                              |
| `502`  | `no_allocations`        | No venue had sufficient liquidity to allocate any portion of the order.                                         |
| `502`  | `all_venues_failed`     | Every dispatched venue failed. Response includes the full Place Order body for diagnosis.                       |
| `503`  | `registry_unavailable`  | Routing 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:

```json theme={null}
{
  "predexonId": "px-uvtpjis2k7bj",
  "side": "buy",
  "amount": "10.00"
}
```

Response (`201`):

```json theme={null}
{
  "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

```json theme={null}
{
  "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.

```json theme={null}
{
  "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.

```json theme={null}
{
  "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." }
}
```

<Info>
  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.
</Info>


## OpenAPI

````yaml POST /api/accounts/{accountId}/router/orders
openapi: 3.1.0
info:
  title: Predexon Order Router API
  description: >-
    Unified cross-venue smart order routing across Polymarket, Predict.fun,
    Opinion, and Limitless
  version: 1.0.0
servers:
  - url: https://trade.predexon.com
security:
  - apiKeyAuth: []
paths:
  /api/accounts/{accountId}/router/orders:
    post:
      tags:
        - router
      summary: Place Market Order
      description: >-
        Place a market order that the router splits across every routed venue
        offering the outcome identified by `predexonId`. Returns the per-venue
        fills, an aggregate summary, and the routing decision. A single response
        may contain fills across multiple venues.


        Identifies the outcome by Predexon canonical ID — the router resolves to
        the full cross-venue equivalence set, checks each enabled venue's
        balance or positions, walks the merged fee-inclusive order books, and
        dispatches per-venue orders in parallel. There is no cross-venue
        atomicity: one venue may fill while another fails, and both outcomes
        surface in `fills[]`.
      operationId: placeRouterOrder
      parameters:
        - name: accountId
          in: path
          required: true
          schema:
            type: string
          description: Account ID. Must belong to the calling API key.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PlaceOrderRequest'
            examples:
              marketBuy:
                summary: Market buy by notional
                value:
                  predexonId: px-uvtpjis2k7bj
                  side: buy
                  amount: '10.00'
              marketSell:
                summary: Market sell by size
                value:
                  predexonId: px-uvtpjis2k7bj
                  side: sell
                  size: '20'
      responses:
        '201':
          description: >-
            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.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PlaceOrderResponse'
              example:
                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).
        '400':
          description: >-
            Validation error, or aggregate balance across enabled venues is
            insufficient for a market buy.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                missingPredexonId:
                  value:
                    error: predexonId required
                    errorCode: parse_error
                invalidSide:
                  value:
                    error: side must be buy or sell
                    errorCode: parse_error
                missingAmount:
                  value:
                    error: amount (finite, >0) required for market buy
                    errorCode: parse_error
                missingSize:
                  value:
                    error: size (finite, >0) required for market sell
                    errorCode: parse_error
                sizeOnMarketBuy:
                  value:
                    error: size must not be set for market buy
                    errorCode: parse_error
                amountOnLimit:
                  value:
                    error: amount must not be set for limit orders
                    errorCode: parse_error
                priceOnMarket:
                  value:
                    error: price must not be set for market orders
                    errorCode: parse_error
                insufficientBalance:
                  value:
                    error: Insufficient balance across enabled venues
                    errorCode: insufficient_balance
        '404':
          description: No routed venue carries the supplied `predexonId`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error: predexonId not found or not routable
                errorCode: predexon_not_routable
        '502':
          description: >-
            Either every dispatched venue failed (`errorCode:
            "all_venues_failed"`), or no venue had sufficient liquidity to
            allocate any portion of the order (`errorCode: "no_allocations"`).
            When `all_venues_failed`, the response includes the full Place Order
            body (`fills[]` and `_routing`) plus `errorCode` so partners can
            diagnose per-venue failures.
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/PlaceOrderResponse'
                  - $ref: '#/components/schemas/ErrorResponse'
              examples:
                noAllocations:
                  value:
                    error: No eligible venues or insufficient liquidity
                    errorCode: no_allocations
                allVenuesFailed:
                  summary: Every dispatched venue failed
                  value:
                    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.
        '503':
          description: >-
            Routing registry is temporarily unavailable. Retry with exponential
            back-off.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error: Registry unavailable (no snapshot loaded)
                errorCode: registry_unavailable
components:
  schemas:
    PlaceOrderRequest:
      type: object
      required:
        - predexonId
        - side
      properties:
        predexonId:
          type: string
          description: >-
            Canonical `predexon_id` for the outcome. The router expands to every
            routed venue listing for that canonical outcome.
        side:
          type: string
          enum:
            - buy
            - sell
        amount:
          type: string
          description: >-
            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:
          type: string
          description: >-
            Number of shares to sell. **Required when `side` is `sell`. Must not
            be set when `side` is `buy`.** Must be a positive decimal string.
    PlaceOrderResponse:
      type: object
      required:
        - routerOrderId
        - predexonId
        - side
        - type
        - requestedAmount
        - requestedSize
        - fills
        - summary
        - _routing
      properties:
        routerOrderId:
          type: string
          description: Unique identifier for this routed order (prefix `rord-`).
        predexonId:
          type: string
          description: Echoes the request `predexonId`.
        side:
          type: string
          enum:
            - buy
            - sell
        type:
          type: string
          enum:
            - market
        errorCode:
          type: string
          description: >-
            Present only on a 502 response when every dispatched venue failed.
            Set to `"all_venues_failed"`. Absent on a 201 success.
          enum:
            - all_venues_failed
        requestedAmount:
          oneOf:
            - type: string
            - type: 'null'
          description: >-
            Echo of the request `amount`. Present (as a stringified number) on
            buy orders; `null` on sell orders.
        requestedSize:
          oneOf:
            - type: string
            - type: 'null'
          description: >-
            Echo of the request `size`. Present (as a stringified number) on
            sell orders; `null` on buy orders.
        fills:
          type: array
          description: >-
            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.
          items:
            $ref: '#/components/schemas/Fill'
        summary:
          $ref: '#/components/schemas/OrderSummary'
        _routing:
          $ref: '#/components/schemas/Routing'
    ErrorResponse:
      type: object
      required:
        - error
      properties:
        error:
          type: string
          description: Human-readable error message.
        errorCode:
          type: string
          description: >-
            Machine-readable error code for switch-case handling. Present on
            every error response and on a 502 Place Order response. Absent on
            successful responses.
          enum:
            - parse_error
            - registry_unavailable
            - predexon_not_routable
            - insufficient_balance
            - no_allocations
            - all_venues_failed
    Fill:
      type: object
      required:
        - venue
        - orderId
        - status
        - size
        - price
        - amount
      properties:
        venue:
          $ref: '#/components/schemas/Venue'
        orderId:
          type: string
          description: >-
            Venue-native order identifier. Use this when reconciling with the
            venue directly.
        status:
          type: string
          enum:
            - filled
            - partial
            - open
            - cancelled
            - failed
          description: Per-fill status as reported by the venue at dispatch time.
        size:
          type: string
          description: Shares matched on this venue.
        price:
          type: string
          description: Volume-weighted average fill price on this venue.
        amount:
          type: string
          description: Notional (stablecoin) matched on this venue.
        fee:
          type: object
          additionalProperties: true
          description: >-
            Venue-native fee data, passed through verbatim from the venue.
            **Field is absent** (not `null`) when the venue does not report fee
            metadata. Shape varies by venue — treat as opaque. For the fee
            factored into the router's ranking, use
            `_routing.considered[].feeBpsAtTop`.
        error:
          type: string
          description: Present only when `status` is `failed`.
    OrderSummary:
      type: object
      required:
        - totalSize
        - totalAmount
        - avgPrice
        - venuesUsed
        - venuesFailed
      properties:
        totalSize:
          type: string
          description: Aggregate shares matched across all venues.
        totalAmount:
          type: string
          description: Aggregate notional matched across all venues.
        avgPrice:
          type: string
          description: Volume-weighted average fill price across all venues.
        venuesUsed:
          type: integer
          description: >-
            Number of venues that successfully produced a fill (status `filled`,
            `partial`, or `open`).
        venuesFailed:
          type: integer
          description: >-
            Number of venues whose dispatch failed. A 201 response can still
            have `venuesFailed > 0`.
    Routing:
      type: object
      description: >-
        Transparency block describing how the router made its allocation
        decision.
      required:
        - considered
        - reasoning
      properties:
        considered:
          type: array
          description: >-
            Venues the router evaluated for the outcome's cross-venue
            equivalence set and could reasonably have routed to. Infrastructure
            dropouts (missing or disconnected books) are excluded. Inspect
            `droppedReason` to see why an included venue received no allocation.
          items:
            type: object
            required:
              - venue
              - avgPrice
              - topLevelPrice
              - droppedReason
              - feeBpsAtTop
            properties:
              venue:
                $ref: '#/components/schemas/Venue'
              avgPrice:
                oneOf:
                  - type: string
                  - type: 'null'
                description: >-
                  Projected volume-weighted price on this venue. `null` when no
                  projected fill.
              topLevelPrice:
                oneOf:
                  - type: string
                  - type: 'null'
                description: Top-of-book price on the relevant side.
              droppedReason:
                oneOf:
                  - type: string
                  - type: 'null'
                description: >-
                  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.
                  Open-ended — treat unknown values as informational.
              feeBpsAtTop:
                type: number
                description: >-
                  Effective venue fee at the top of book in basis points. May be
                  fractional.
        reasoning:
          type: string
          description: >-
            Natural-language explanation of the routing decision. Suitable for
            logs and dashboards.
    Venue:
      type: string
      enum:
        - polymarket
        - predict
        - opinion
        - limitless
      description: A routed venue.
  securitySchemes:
    apiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: >-
        Trading key provided by Predexon. The data key used by the Sports
        Discovery API on api.predexon.com is a separate credential.

````