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

# ProphetX

> Addressing strikes, stake and price, execution policy and cancellation on ProphetX.

ProphetX is an account venue: an admin connects the venue credential at the
organization and ties it to a pod, and traders in that pod trade through the tie.
Submitting or cancelling an order needs a key with the `trade` capability.

Every endpoint is listed under [ProphetX](/api-reference/prophetx/submit-order)
in the API reference, and they answer 404 for an account that does not have
ProphetX available. Contact support if you need access. `@parlayx/sdk` and
Python `parlayx` reach all of them through `client.prophetx`.

## Addressing a market

`strikeId` identifies the market and the side together, and it is the same id
discovery returns. `GET /v1/sports/events/{eventId}/markets` reports a
`strikeId` on each ProphetX outcome, and the market data stream subscribes by
the same id.

A 404 means the venue does not list that strike. `strikeId` is validated before
any other field, so a bad strike is reported ahead of a malformed request's 400.

## Sizing and pricing

`quantity` is the stake in dollars, not a share count. `price` is the cost of
one share in dollars, the same unit Polymarket, Kalshi and Limitless price in.

Each share settles at one dollar or nothing. A fill reports `shares`, the
per-share cost in `price`, and the stake it consumed in `stakeUsd`.

### The prices the venue quotes

ProphetX quotes a fixed set of prices rather than every value the field accepts.
The set runs from 0.003984 to 0.996016, and the gaps between neighbouring prices
widen towards the middle of the range, from 0.000081 at the ends to 0.005464 at
their widest.
[Get Price Ladder](/api-reference/prophetx/get-price-ladder) returns the current
set.

> [!WARNING]
>
> New orders require an exact price from the current submission ladder.
> Off-ladder prices are rejected with `400 INVALID_REQUEST`, not rounded.
> An in-range rejection names the neighboring valid prices; choose one
> explicitly before submitting a new order.

Sending `0.840336` when the neighboring ladder prices are `0.838710` and
`0.841270` is rejected. The higher price exceeds the stated limit; it is not
selected automatically. A price observed in a fill or orderbook is not
necessarily an available submission price.

A price past either end of the set is refused with 400 rather than moved.

## Execution policy

| `timeInForce` | Behavior |
| - | - |
| Omitted or `{ "type": "GTC" }` | Rest until filled or cancelled. |
| `{ "type": "FOK" }` | The venue's fill-or-kill. Cancelled at the venue if no match is made within about two seconds. |
| `{ "type": "GTD", "expiresAt": "2026-10-01T12:00:00Z" }` | Rest until the stated time, then cancel whatever stake is still open. |

`postOnly: true` is accepted with GTC and GTD. `FOK` accepts an omitted
`postOnly` or `false`, and combining it with `true` returns 400 before
submission.

> [!NOTE]
>
> This follows the venue's own fill-or-kill rather than the immediate one on
> Polymarket, Kalshi and Limitless: an unmatched order rests for up to about two
> seconds before the venue withdraws it. The venue does not state what happens
> to a partially filled remainder, so read the order's status and its fills to
> establish the result.

The two-second window belongs to venue processing, not to the HTTP request's
round trip. A 201 is still only an acknowledgement.

```json theme={null}
{
  "strikeId": "e70297b294c7157d3dabb7d84ea09947",
  "price": "0.400000",
  "quantity": 25,
  "timeInForce": { "type": "FOK" }
}
```

### Good til date

Send `expiresAt` as an ISO-8601 UTC timestamp ending in `Z`, at least five
seconds ahead. A timestamp inside that window, or already past, is refused with
400 `INVALID_REQUEST` before an order is created. The timestamp you sent is
reported back on order reads.

> [!WARNING]
>
> ProphetX has no expiry of its own, so the deadline is kept by ParlayX
> cancelling the order. The five-second minimum is an admission rule, not a
> cancellation guarantee: the cancel is paced against the venue's budget of one
> write a second and queues behind whatever else the account is sending, so an
> order can still fill after its stated time. Read the order's status and its
> fills to establish the result. While the venue is unreachable there is no
> guaranteed cancellation time at all.

Once the cancellation is confirmed, the order reads `CANCELLED` with
`cancellationReason: "EXPIRED"`. A deadline that passes while the cancellation
is still uncertain leaves the order in the status it already had, and the
attempt is repeated: elapsed time alone never moves an order to cancelled. A
fill that lands first wins, so a fully matched order reads `FILLED` and a
partial fill stays an execution with `filledQuantity` reporting the matched
stake.

Replaying an idempotency key returns the order it already named, whether or not
that order's deadline has passed. A new request carrying a past deadline is
refused.

GTD is accepted on `POST /v1/prophetx/orders` only, and a batch entry carrying
it is refused with 400. One cancellation at a time against a budget of one write
a second is not a deadline twenty orders can share.

```json theme={null}
{
  "strikeId": "e70297b294c7157d3dabb7d84ea09947",
  "price": "0.400000",
  "quantity": 25,
  "postOnly": true,
  "timeInForce": { "type": "GTD", "expiresAt": "2026-10-01T12:00:00Z" }
}
```

## Submitting

A 201 means the order was accepted, not that the venue holds it. The `status` it
returns is the order's recorded state when the response was produced, so read the
order back to learn whether it rested or filled. A retry under the same idempotency
key returns the order it already created, carrying whatever state that order has
now.

ProphetX then acknowledges before it matches, so even its acknowledgement never
tells you whether the order executed.

### What the receipt says

`orderId` is the id you use everywhere in this API. `venueOrderId` is ProphetX's own
id for the same order, carried so that reconciling against the venue's records needs
no second call.

`price` is the order's accepted limit in dollars per share. New orders do not
round the submitted price. Older orders may retain a rounded limit; an identical
idempotent retry returns the existing order without repricing it. This field is
not an execution price or an average fill price, and its presence is not evidence
the order is resting.

`quantity` is the stake the order was submitted with. It is not decremented as the
order fills, so an order submitted for 25 still reads 25 after a partial fill, after a
cancellation and after completion. It is neither remaining stake nor filled stake. Read
`filledQuantity` on the order to learn what has matched.

> [!WARNING]
>
> `venueOrderId` is null when no venue order id has been recorded. That is a statement
> about our record, not about ProphetX: it covers an order the venue refused, and it
> also covers an order the venue is holding whose acknowledgement never reached us.
> Never read null as proof that nothing was placed and that submitting again is safe.
> Read the order back, or retry the identical order under its original idempotency key.

Replaying an idempotency key returns the order's current recorded `status` alongside
the terms it was originally submitted with. It does not replay the original
acknowledgement and it does not report how much of the order is still open. Reusing a
key with a different request body places nothing and returns 422 `IDEMPOTENCY_CONFLICT`.

### Batch submit

[Batch Submit Orders](/api-reference/prophetx/batch-submit-orders) places up to 20
GTC or FOK orders in one request under one `Idempotency-Key` header. Each order gets its own
outcome, so one refused order does not fail the others. A `200` means the batch was
read, not that every order was placed. The response holds two lists, and every order
in the request appears in exactly one of them:

| List | Meaning |
| - | - |
| `succeededOrders` | Accepted, not confirmed at the venue, and not a fill. A replayed entry reports the order's current state. Each carries the same fields as a single submit's receipt: `orderId`, `status`, `price`, `venueOrderId` and `quantity`. |
| `failedOrders` | Refused, or not confirmed. Each carries `orderId` (null when no order id is known) and an `error` with `code` and `message`. |

```json theme={null}
{
  "succeededOrders": [
    {
      "orderId": "0199a3f2-5b7c-7d10-9e2f-3a4b5c6d7e8f",
      "status": "OPEN",
      "price": "0.400000",
      "venueOrderId": "partner_6c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
      "quantity": 25
    }
  ],
  "failedOrders": [
    {
      "orderId": "0199a3f2-5b7c-7d10-9e2f-3a4b5c6d7e90",
      "error": {
        "code": "ORDER_RECONCILIATION_REQUIRED",
        "message": "Read this order to establish its outcome. Do not submit it under a new idempotency key."
      }
    }
  ]
}
```

* `ORDER_RECONCILIATION_REQUIRED`: the order may be resting, so this is not proof nothing was placed. Read `orderId` back before retrying.
* `INTERNAL_ERROR` with a null `orderId`: retry the identical order under the same idempotency key.
* Any other code: the entry was refused and not placed.

Retry by resending the whole batch, identical, under the same key: orders already
recorded come back as they are, with the same `orderId`, and only the rest are placed.
The same key with a different batch returns 422 `IDEMPOTENCY_CONFLICT` and places
nothing. A new key places every order again.

A failed entry with a null `orderId` cannot yet be matched to the order you sent.

A FOK entry follows the single order's rules. `postOnly: true` on a FOK entry
refuses the whole batch with 400 before anything is placed. An unmatched FOK
entry is cancelled at the venue after about two seconds, and the other entries
in the batch are not affected. A FOK entry in `succeededOrders` was accepted,
not filled: read the order's status and its fills to establish the result.

## Cancelling

Cancel by the issued order id. An order that had already filled, or had already
cancelled, comes back with 200 and its terminal status rather than as an error.
This venue acknowledges before it matches, so a fill can land between the submit
and the cancel.

A 409 means the order cannot be addressed at the venue yet, because
`venueOrderId` is null until the venue acknowledges it. Read the order and retry
once it carries one. A 503 is the venue's own try-again family, most often a
cancel arriving while the submit for the same order is still in flight. Repeat
the request.

### Endings the venue decides

ProphetX can end an order on its own, by cancelling, voiding, wiping or
invalidating it, and at kickoff it wipes what is still resting. It sends no
cancellation you can subscribe to, so the order is reconciled against the venue
on a schedule.

> [!WARNING]
>
> An order ended by the venue keeps reading `OPEN` here until reconciliation
> catches up, typically tens of minutes and with no guaranteed upper bound. Do
> not build a timeout from it, and treat a resting order near kickoff as
> unresolved rather than live.

## Reading orders and fills

`filledQuantity` on the order reads the fill ledger while the order is working,
so it reports matched stake as fills land rather than only once the order
closes. It is null until the first fill is recorded. Read
[Get Order Fills](/api-reference/prophetx/get-order-fills) for the individual
matches.

> [!WARNING]
>
> A match can arrive before its trade details are available. Until the fill is
> recorded, the order can still read `OPEN` with `filledQuantity: null` and an
> empty fills list, including after the FOK matching window has elapsed. These
> reads do not prove the order failed to execute.
>
> Keep reading the same order and its fills to establish the result. If you
> retry submission, send the identical request under its original idempotency
> key. Submitting under a new key creates another order and can duplicate the
> trade. There is no guaranteed maximum delay before fill details appear.

Orders report no average price, because the venue records one only once the
order closes. Aggregate the fills instead, which carry each match at its own
price.

## Limits and pacing

ProphetX budgets writes at one per second per account. Orders are paced against
that budget and retried once. A 429 means the pacing did not recover the
request, and the account is submitting faster than the venue accepts.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.