Skip to main content
GET
/
api
/
accounts
/
{accountId}
/
router
/
positions
List Positions
curl --request GET \
  --url https://trade.predexon.com/api/accounts/{accountId}/router/positions \
  --header 'x-api-key: <api-key>'
{
  "positions": [
    {
      "predexonId": "px-uvtpjis2k7bj",
      "title": "Atlanta Hawks",
      "outcome": "atl",
      "size": "29.935000",
      "averagePrice": "0.335488",
      "currentPrice": "0.352000",
      "currentValue": "10.537120",
      "pnl": "0.495042",
      "status": "active",
      "result": null,
      "venues": [
        {
          "venue": "polymarket",
          "size": "18.115000",
          "averagePrice": "0.331200",
          "currentPrice": "0.352000",
          "currentValue": "6.376480",
          "pnl": "0.376842",
          "status": "active",
          "result": null
        },
        {
          "venue": "predict",
          "size": "11.820000",
          "averagePrice": "0.342000",
          "currentPrice": "0.352000",
          "currentValue": "4.160640",
          "pnl": "0.118200",
          "status": "active",
          "result": null
        }
      ]
    }
  ],
  "unmapped": [
    {
      "venue": "polymarket",
      "tokenId": "59005039819817191572790632185216584675790282938177567233176230080432531995226",
      "predexonId": "px-fegdlyupysfg",
      "size": "1.49",
      "averagePrice": "0.666798",
      "title": "Spurs vs. Trail Blazers",
      "outcome": "Spurs",
      "status": "redeemable",
      "result": "won"
    },
    {
      "venue": "polymarket",
      "tokenId": "8501497159083948713316135768103773293754490207922884688769443031624417212426",
      "predexonId": "px-ytpcgddmjldm",
      "size": "5.45",
      "averagePrice": "0.549999",
      "title": "Russia-Ukraine Ceasefire before GTA VI?",
      "outcome": "Yes",
      "status": "active",
      "result": null
    }
  ],
  "_meta": {
    "venues": [
      {
        "venue": "polymarket",
        "status": "ok"
      },
      {
        "venue": "predict",
        "status": "ok"
      },
      {
        "venue": "opinion",
        "status": "ok"
      },
      {
        "venue": "limitless",
        "status": "ok"
      }
    ]
  }
}

Overview

Return the account’s open positions grouped by outcome. The router fans out position reads to every routed venue in parallel, then groups per-venue holdings under a single predexon_id. One position per outcome surfaces even when the partner holds it across multiple venues. Per-venue breakdowns are available on positions[].venues[]. Top-level fields use the same names as their per-venue counterparts (size, averagePrice, currentPrice, currentValue, pnl, status, result) — the enclosing scope disambiguates. Each position carries:
  • Cost basis (averagePrice) sourced directly from each venue’s execution plane, which already tracks weighted-average cost across every source of fills — the router does not recompute attribution.
  • Live pricing (currentPrice, currentValue, pnl) computed by the router from the streaming order-book feed using each venue’s current top bid. Plane-reported values for these are intentionally not forwarded — they’re periodic REST snapshots and would mislead partners on time-sensitive decisions.
  • Lifecycle state (status, result) passed through from the plane.
See the Order Router concept page for how predexon_id groups equivalent outcomes across venues.

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.

Response Fields

Top level

FieldTypeDescription
positions[]arrayPositions aggregated by predexon_id. One entry per outcome.
unmapped[]arrayPositions the router doesn’t carry on its live trading surface (resolved sports markets, non-sports markets). Surfaced as flat per-venue records — no cross-venue aggregation, no live pricing. See Unmapped positions.
_meta.venues[]arrayPer-venue read status.

Position entry

Fields are aggregated across every venue that holds the position. Per-venue values are preserved in venues[].
FieldTypeDescription
predexonIdstringCanonical identifier of the outcome this position is in.
titlestringHuman-readable outcome label.
outcomestringCanonical outcome code.
sizestringTotal shares held across every venue.
averagePricestring?Size-weighted mean of each venue’s averagePrice (cost basis). Venues whose plane reports null are skipped from the weighting.
currentPricestring?Size-weighted mean of each venue’s current top bid — equivalent to currentValue / size. null only when no venue has a live book for this outcome.
currentValuestring?Aggregate market value of the position in stablecoin. Sum of per-venue size × currentPrice across venues with live books.
pnlstring?Unrealised profit and loss in stablecoin. currentValue − sum(size × averagePrice) across the contributing venues.
statusstring?active, redeemable, or resolved. null when no venue has reported a status yet. See Lifecycle.
resultstring?won, lost, or null.
venues[]arrayPer-venue breakdown.

Per-venue entry

Every field on the position entry exists at the per-venue level with the per-venue value.
FieldTypeDescription
venuestringpolymarket, predict, opinion, or limitless.
sizestringShares held on this venue.
averagePricestring?Weighted-average cost basis on this venue, as reported by the venue’s execution plane across every source of fills (router orders plus any direct per-venue orders).
currentPricestring?Top bid on this venue from the router’s live order-book feed.
currentValuestring?size × currentPrice. null when no live book is available.
pnlstring?currentValue − (size × averagePrice).
statusstring?active, redeemable, or resolved.
resultstring?won, lost, or null.

Unmapped position entry

unmapped[] carries positions the router cannot aggregate or live-price. Two cases produce these:
  1. Sports markets that have resolved. Once the game finishes, the market drops off the router’s live trading surface, but the partner still holds the redeemable token until claimed.
  2. Non-sports markets (politics, news, crypto-binary, etc.). The router only routes sports markets, so positions on other markets always surface here — even while the market is fully active on its native venue.
Each entry is per-venue (no aggregation). currentPrice, currentValue, and pnl are omitted — they require a live order book that isn’t available for these markets. Use the per-venue read at GET /api/accounts/{accountId}/positions?venue={venue} if you need live pricing on an unmapped position.
FieldTypeDescription
venuestringpolymarket, predict, opinion, or limitless.
tokenIdstringThe venue-native token identifier for this position.
predexonIdstring?Canonical identifier of the outcome this position is in.
sizestringShares held on this venue.
averagePricestring?Cost basis.
titlestring?Human-readable outcome label.
outcomestring?Outcome code as reported by the venue (may differ from the canonical sports outcomes endpoint).
statusstring?active, redeemable, or resolved.
resultstring?won, lost, or null.

_meta.venues[]

Per-venue read status. When a venue returned error, its positions are not reflected in the aggregated response — the other venues still return normally.
FieldTypeDescription
venuestring
statusstringok or error.

Lifecycle

status

ValueMeaning
activeThe market is still open and the position is tradeable.
redeemableThe market has resolved in the partner’s favour and the position can be redeemed for stablecoin.
resolvedThe market has resolved and the position is fully settled — either redeemed already, or resolved with no payout.
nullNo venue has reported a lifecycle status for this position yet.

result

ValueMeaning
nullMarket is still active, or not every venue has finalised.
wonOutcome resolved in the partner’s favour on at least one venue — there is something to claim.
lostEvery venue reported lost.

Aggregation across venues

When a position exists on multiple venues, the top-level fields are derived from each venue as follows:
Top-level fieldRule
sizeSum of per-venue size.
averagePriceSize-weighted mean of per-venue averagePrice, skipping venues whose plane reported null.
currentPriceSize-weighted mean of per-venue top bid (equivalent to currentValue / size).
currentValueSum of per-venue size × currentPrice. Venues without a live book contribute nothing.
pnlcurrentValue − sum(size × averagePrice) across contributing venues.
statusAny activeactive. Else any redeemableredeemable. Else resolved. null if no venue reported a status.
resultAny wonwon. All lostlost. Else null.

Example

GET /api/accounts/acc_8f2e/router/positions
{
  "positions": [
    {
      "predexonId": "px-uvtpjis2k7bj",
      "title": "Atlanta Hawks",
      "outcome": "atl",
      "size": "29.935000",
      "averagePrice": "0.335488",
      "currentPrice": "0.352000",
      "currentValue": "10.537120",
      "pnl": "0.495042",
      "status": "active",
      "result": null,
      "venues": [
        {
          "venue": "polymarket",
          "size": "18.115000",
          "averagePrice": "0.331200",
          "currentPrice": "0.352000",
          "currentValue": "6.376480",
          "pnl": "0.376842",
          "status": "active",
          "result": null
        },
        {
          "venue": "predict",
          "size": "11.820000",
          "averagePrice": "0.342000",
          "currentPrice": "0.352000",
          "currentValue": "4.160640",
          "pnl": "0.118200",
          "status": "active",
          "result": null
        }
      ]
    }
  ],
  "unmapped": [
    {
      "venue": "polymarket",
      "tokenId": "59005039819817191572790632185216584675790282938177567233176230080432531995226",
      "predexonId": "px-fegdlyupysfg",
      "size": "1.49",
      "averagePrice": "0.666798",
      "title": "Spurs vs. Trail Blazers",
      "outcome": "Spurs",
      "status": "redeemable",
      "result": "won"
    },
    {
      "venue": "polymarket",
      "tokenId": "8501497159083948713316135768103773293754490207922884688769443031624417212426",
      "predexonId": "px-ytpcgddmjldm",
      "size": "5.45",
      "averagePrice": "0.549999",
      "title": "Russia-Ukraine Ceasefire before GTA VI?",
      "outcome": "Yes",
      "status": "active",
      "result": null
    }
  ],
  "_meta": {
    "venues": [
      { "venue": "polymarket", "status": "ok" },
      { "venue": "predict", "status": "ok" },
      { "venue": "opinion", "status": "ok" },
      { "venue": "limitless", "status": "ok" }
    ]
  }
}
currentPrice, currentValue, and pnl are computed by the router using the live top-of-book bid for each venue — they are not passed through from plane-reported values, which can be stale. averagePrice is always plane-sourced and reflects every fill that contributed to the position, including fills from sources outside the router.
When _meta.venues[].status is error for any venue, the aggregated positions[] reflects only the healthy venues. Re-call the endpoint after a short delay to pick up the missing venue once reads recover — a brief transient on one venue does not roll back the response.
unmapped[] is not a degraded mode — it’s the design for any position outside the router’s live trading surface. Resolved sports positions (waiting to be redeemed) and non-sports positions (politics, news, etc.) belong here permanently. Reconcile against predexonId like you would for positions[]. The shape is intentionally flatter (no venues[] aggregation, no live pricing) — partners that need a live price for these positions should call GET /api/accounts/{accountId}/positions?venue={venue}.

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.

Response

200 - application/json

Positions aggregated across routed venues.

positions
object[]
required

Positions aggregated by predexonId. One entry per outcome, regardless of how many venues the partner holds it on.

unmapped
object[]
required

Positions the router doesn't carry on its live trading surface. Two cases: (1) sports markets that have resolved (status: resolved or redeemable); (2) non-sports markets (politics, news, crypto-binary), which always surface here. No aggregation, no live pricing.

_meta
object
required