The lifecycle channel ("lifecycle") delivers two event types: token_registered and condition_resolution.
token_registered
Emitted when a new market’s outcome tokens are registered on-chain. This is the earliest signal that a new market exists. Metadata fields (title, market_slug, etc.) may be null for brand-new markets since off-chain metadata may not yet be available.
{
"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.
{
"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 |
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.
Field Reference
| Field | Type | Description |
|---|
event_type | "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 |
Example: Monitoring Resolutions
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}`);
}
};