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

# User Fills

> Your own executions, with fees and your order id.

A `prediction-fill` message is sent when one of your orders executes. It is
delivered inside a `prediction-market-update` envelope on your private stream.

## Access

Requires an API key with the `read` scope. Send an
[`authenticate`](/websockets/connection) frame; there is no separate subscribe
for the private stream.

```json theme={null}
{"type":"authenticate","data":{"token":"soar_sk_..."}}
```

## Fields

| Field | Type | Description |
| - | - | - |
| `type` | string | Always `"prediction-fill"` |
| `orderId` | **string** | Your order's id. See the warning below |
| `tradeId` | number | Engine sequence number for the match |
| `eventMarketId` | string | UUID of the market |
| `side` | string | `"buy"` or `"sell"` — your side |
| `outcome` | string | `"yes"` or `"no"` — the outcome you hold |
| `price` | number | Canonical match price in cents, from the YES perspective |
| `fillPrice` | number | The price **you** filled at, in cents |
| `qty` | number | Shares filled in this execution |
| `isTaker` | boolean | `true` if your order crossed, `false` if it was resting |
| `feeCents` | number | Fee charged on this fill, in cents |
| `ts` | number | Unix timestamp in **nanoseconds** |

<Warning>
  **`orderId` is a string, and must stay one.** It is a 63-bit hash from the
  matching engine that exceeds `Number.MAX_SAFE_INTEGER`. Parsing it as a
  number silently corrupts it — `JSON.parse` in JavaScript will round it, and
  the id you send back will not match the one you received.

  Compare and store it as a string.
</Warning>

## `price` vs `fillPrice`

`price` is the canonical price of the match, always expressed from the YES
perspective — it is the same value both counterparties see.

`fillPrice` is that same match from **your** side. If you hold NO, your
economics are the complement of the canonical price, and `fillPrice` reflects
that. Use `fillPrice` for your own cost basis and P\&L; use `price` when
correlating against the [public tape](/websockets/public-trades), which reports
the canonical price.

## Example

```json theme={null}
{
  "type": "prediction-market-update",
  "data": {
    "type": "prediction-fill",
    "orderId": "7284619305827364910",
    "tradeId": 184203,
    "eventMarketId": "9f1c2d3e-4a5b-6c7d-8e9f-0a1b2c3d4e5f",
    "side": "buy",
    "outcome": "yes",
    "price": 62,
    "fillPrice": 62,
    "qty": 40,
    "isTaker": true,
    "feeCents": 12,
    "ts": 1789238400123456789
  }
}
```

## Notes

* **One message per execution.** An order that crosses several resting orders
  produces several fills, each with the same `orderId` and a different
  `tradeId`. Sum `qty` across them for the total, or read `filledQty` from the
  matching [order update](/websockets/user-orders).
* Fills and order updates arrive independently. Do not assume an ordering
  between a `prediction-fill` and the `prediction-order` that reflects it.
* This replaces polling `GET /v1/portfolio/fills`. Authenticate and buffer live
  events before loading REST history, then reconcile and deduplicate by `tradeId`.
  See [Replacing REST polling](/websockets/connection#replacing-rest-polling).


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