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

# Lifecycle Events

> Real-time token registrations and market resolutions

The lifecycle channel (`"lifecycle"`) delivers three event types: `condition_prepared`, `token_registered`, and `condition_resolution`.

<Note>
  **V1 vs V2:** `condition_prepared` fires for both V1 and V2 markets (new market signal from `ConditionalTokens`). `token_registered` is **V1-only** - V2 exchanges no longer emit it. Use `condition_prepared` as your "new market" signal to cover both. See the [V2 Migration Guide](/websocket/v2-migration).
</Note>

## condition\_prepared

Emitted when a new condition is created on the shared `ConditionalTokens` contract. Fires for both V1 and V2 markets.

For **binary markets** (`outcome_slot_count === 2`), token IDs are derived deterministically from `(condition_id, is_neg_risk)` using the CTF Gnosis formula and included in the `tokens` array. For non-binary markets, `tokens` is `null` - query Gamma or CLOB by `condition_id` to resolve them.

```json theme={null}
{
  "type": "event",
  "subscription_id": "sub_2f4b15b33798",
  "data": {
    "event_type": "condition_prepared",
    "condition_id": "0xa7ff1749...",
    "oracle": "0x65070be91477460d8a7aeeb94ef92fe056c2f2a7",
    "question_id": "0xb5bd0abc...",
    "tx_hash": "0xabc...",
    "log_index": "0xe5",
    "block_number": "0x51bfb94",
    "timestamp": 1776559955,
    "title": null,
    "market_slug": null,
    "market_id": null,
    "image": null,
    "tokens": [
      { "token_id": "1234567890...", "label": "Yes" },
      { "token_id": "9876543210...", "label": "No" }
    ],
    "is_neg_risk": false,
    "outcome_slot_count": 2
  }
}
```

* Metadata fields (`title`, `market_slug`, `market_id`, `image`) are always `null` at prepare time.
* `tokens` is populated for binary markets (`outcome_slot_count === 2`) with derived token IDs. `null` otherwise.
* **Token labels** (`"Yes"` / `"No"`) are **placeholders** - clients should resolve canonical labels via Gamma/CLOB once market metadata is indexed.
* `is_neg_risk` is derived from the oracle address (`true` if oracle = `NegRiskAdapter`).
* `outcome_slot_count` is the number of outcomes for the condition (typically `2`).

## token\_registered

<Warning>
  **V1 only.** V2 exchanges no longer emit `TokenRegistered`. Use `condition_prepared` above for new market signals that cover both V1 and V2.
</Warning>

Emitted when a new V1 market's outcome tokens are registered on-chain. Metadata fields (`title`, `market_slug`, etc.) may be null for brand-new markets since off-chain metadata may not yet be available.

```json theme={null}
{
  "type": "event",
  "subscription_id": "sub_2f4b15b33798",
  "data": {
    "event_type": "token_registered",
    "condition_id": "0x197047c17a5111889b1090b979105a8822774a8f173085f0703f311eeff91804",
    "oracle": null,
    "question_id": null,
    "tx_hash": "0xbdb667d47544cd25dfe8a03e53a287cb6cc073ae502887efbd07ac15120aa9f6",
    "log_index": "0x1b7",
    "block_number": "0x4ebcd5f",
    "timestamp": 1770244805,
    "title": null,
    "market_slug": null,
    "market_id": null,
    "image": null,
    "tokens": [
      { "token_id": "2505367458...", "label": "Unknown" },
      { "token_id": "3237569069...", "label": "Unknown" }
    ],
    "is_neg_risk": false
  }
}
```

## condition\_resolution

Emitted when a market resolves. The `tokens` array includes a `won` field indicating which outcome won. For voided or non-standard resolutions, the `is_invalid` field is set to `true` and all token `won` fields are `false`.

```json theme={null}
{
  "type": "event",
  "subscription_id": "sub_2f4b15b33798",
  "data": {
    "event_type": "condition_resolution",
    "condition_id": "0x6b6de56b0057be1b236ef4e52745ca1160497419789ffe3c6f0f95b12e195762",
    "oracle": "0x6a9d222616c90fcd177a525e9fa661a564a67b14",
    "question_id": "0x1234...",
    "tx_hash": "0x...",
    "log_index": "0x...",
    "block_number": "0x...",
    "timestamp": 1770244800,
    "title": "Will Sunderland AFC win on 2026-02-02?",
    "market_slug": "epl-sun-bur-2026-02-02-sun",
    "market_id": "1225150",
    "image": "https://polymarket-upload.s3.us-east-2.amazonaws.com/...",
    "is_neg_risk": false,
    "is_invalid": false,
    "tokens": [
      { "token_id": "3331904137...", "label": "Yes", "won": true },
      { "token_id": "9751235886...", "label": "No", "won": false }
    ]
  }
}
```

### `is_invalid` behavior

When Polymarket resolves a market with a non-standard payout vector (anything other than `[0,1]` or `[1,0]`), the event includes `is_invalid: true` and all token `won` fields are set to `false`. This covers voided markets, split resolutions (e.g. 50/50 refunds), and other non-standard outcomes.

| Payout vector | `is_invalid` | Token `won` values | Meaning                               |
| ------------- | ------------ | ------------------ | ------------------------------------- |
| `[1, 0]`      | `false`      | `[true, false]`    | Normal resolution - first token wins  |
| `[0, 1]`      | `false`      | `[false, true]`    | Normal resolution - second token wins |
| `[1, 1]`      | `true`       | `[false, false]`   | Voided/split - 50/50 refund           |
| `[0, 0]`      | `true`       | `[false, false]`   | Invalid resolution                    |
| Any other     | `true`       | `[false, false]`   | Non-standard payout                   |

<Warning>
  **Breaking semantic change:** Previously, voided markets showed `won: true` on both tokens. Now they show `won: false` on both tokens with `is_invalid: true`. Clients that relied on the old behavior should update to check `is_invalid`.
</Warning>

## Field Reference

| Field                | Type                                                                       | Description                                                                  |
| -------------------- | -------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
| `event_type`         | `"condition_prepared"` \| `"token_registered"` \| `"condition_resolution"` |                                                                              |
| `condition_id`       | string                                                                     | Market condition ID                                                          |
| `oracle`             | string \| null                                                             | Oracle address (resolution only)                                             |
| `question_id`        | string \| null                                                             | Question ID (resolution only)                                                |
| `is_neg_risk`        | boolean                                                                    | Whether this is a neg-risk market                                            |
| `is_invalid`         | boolean                                                                    | `true` when the market resolved with a non-standard payout (resolution only) |
| `tokens`             | array \| null                                                              | Outcome tokens; includes `won` boolean on resolution events                  |
| `title`              | string \| null                                                             | Market title                                                                 |
| `market_slug`        | string \| null                                                             | Market URL slug                                                              |
| `market_id`          | string \| null                                                             | Internal market ID                                                           |
| `image`              | string \| null                                                             | Market image URL                                                             |
| `tx_hash`            | string                                                                     | Transaction hash                                                             |
| `log_index`          | string                                                                     | Log index (hex)                                                              |
| `block_number`       | string                                                                     | Block number (hex)                                                           |
| `timestamp`          | number                                                                     | Unix timestamp in seconds                                                    |
| `outcome_slot_count` | number \| null                                                             | Number of outcomes (present on `condition_prepared` only)                    |
| `version`            | number \| null                                                             | `1` for V1 contracts, `2` for V2 contracts                                   |

## Example: Monitoring Resolutions

```javascript theme={null}
ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);

  if (msg.type === 'event' && msg.data.event_type === 'condition_resolution') {
    const data = msg.data;

    if (data.is_invalid) {
      console.log(`Market voided/invalid: ${data.title}`);
      console.log(`Condition: ${data.condition_id}`);
      return;
    }

    const winner = data.tokens.find(t => t.won);
    console.log(`Market resolved: ${data.title}`);
    console.log(`Winner: ${winner?.label}`);
    console.log(`Condition: ${data.condition_id}`);
  }
};
```
