Skip to main content
This page describes the release candidate. Self-service activation, recent replay, historical delivery and coverage certification are not generally available yet. A captured range is not automatically an audited range.

Access

On-chain Events uses your organisation’s WebSockets key, an active Build plan or above, and explicit grants for the event families you select. Book and fills access does not grant these families. API secrets remain in your backend. The Console candidate provides On-chain Events → Activate access → Connect. An owner or administrator enables new organisation families. Developers may configure keys within the organisation’s enabled families. Billing membership does not grant credential access. The token-registration family targets the legacy CTF exchanges that emit TokenRegistered. The inspected current CTF Exchange V2 ABIs do not declare that event. Native preparation events are a separate family; they must not be relabeled as CTF token-registration logs. Stream and historical grants are independent. Coverage is declared separately for CTF and Protocol V2. Native Protocol V2 does not emit a CTF preparation event for every condition. The candidate covers historical and current declarations for combo condition/event splits and merges, event conversion, and YES-basket conversion/merge. The four inspected implementation epochs use 14 distinct signatures for these operations. The candidate additionally decodes inspected position-migration, compression, extract/inject, wrap/unwrap, bridge, migration-registration and result-reporting declarations. This completes software support for the selected implementation ABI inventory; full native lifecycle coverage over a historical range is not certified. Combo transformations use the existing collateral family with kind equal to split, merge or convert. payload.operation distinguishes split_on_condition, merge_on_condition, split_on_event, merge_on_event, convert_on_event, convert_to_yes_basket and merge_from_yes_basket. Their amount_unit is position_base_units: transforming an existing position does not represent a new collateral deposit, trade volume or fee revenue. condition_id is the parent/full condition carried by the log; parent_condition_id, child YES/NO condition IDs and native_event_id are preserved where declared. Market filtering matches that primary condition; it does not expand the event into underlying legs or child-market activity. Current declarations carry a recipient, two recipients or an ordered recipients array. Arrays preserve repeated addresses and their original order. Historical declarations without recipient fields leave them absent. The candidate limits recipient arrays to 256 entries; an oversized or malformed event halts capture without advancing its checkpoint. This is a decoder limit, not an asserted protocol maximum. With a pinned implementation, a signature not declared for that implementation is rejected. These are software guarantees; the deployment registry, historical range and on-chain occurrences still require certification. The candidate decoder also supports MigrationResolved on the binary and NegRisk modules. These frames use type: "resolution" and kind: "migration_resolved". condition_id identifies the native condition; legacy_condition_id identifies its linked CTF condition. legacy_payouts preserves the two original payout numerators and legacy_payout_denominator their sum. payouts preserves the normalized native numerators with payout_denominator: "1000000". These are resolution ratios, not trade volume or collateral amounts. Distinct logs for the same condition retain distinct event IDs; do not count multiple resolution logs as multiple market settlements. Software acceptance does not certify the historical completeness of these frames.

Additional native lifecycle operations

These operations share the existing family grants; they do not create new token types or change the byte tariff. The operation names below identify payload.operation, rather than always matching the top-level kind:
  • Compression, extract/inject and wrap/unwrap use kind: "convert".
  • Bridge mint/burn use kind: "bridge".
  • Position migration uses kind: "migrate" and operation: "migrate_position".
  • Legacy collateral settlement uses kind: "settle" and operation: "legacy_collateral_settlement".
  • The preparation and result-availability operations below use their operation name as kind.
Use both fields when classifying transformations. A conversion frame does not, by itself, prove a NegRisk conversion or a collateral deposit. The decoder uses 18 additional exact signatures from 52 inspected declarations, including historical recipient-less forms. Historical combo ABIs declare bridge events that the current combo ABI does not; implementation/ABI guards preserve that distinction. Bridge arrays are canonical, paired and bounded to 256 entries. Malformed, mismatched, oversized or unrecognized-epoch input halts capture. Condition filtering matches explicit condition attribution. A log carrying only position IDs does not acquire an inferred Polymarket market identity. Such logs remain in the firehose and, where an actor/recipient is declared, wallet output; complete per-market coverage also requires a verified position-to-market registry. Likewise, logs without a declared wallet cannot be presented as wallet flows. Administrative role/ownership/initialization events are outside these lifecycle families; ERC1155 transfers are not implicitly included. Do not interpret absence from a filtered response as proof of no activity.

Candidate connection contract

The API candidate accepts a signed GET /mempool/token?families=... request and returns a short-lived grant. Use the edge address configured for the same environment, at /ws/onchain. Reconnecting requires a fresh grant. Never reuse production destinations as a staging fallback.
The versioned socket is separate from legacy /ws so legacy collateral frames cannot be confused with the new schema. A revoked or expired credential loses access. The candidate uses a maximum 30-second revocation recheck interval; expiry has a deadline timer.

Capabilities and API reference

Use the same signed request format as the other Bravado market-data endpoints: GET /v1/polymarket/onchain/capabilities. The response reports your current plan access, independent stream/history permissions for all four families, the effective bytes tariff, canonical endpoint paths and whether recent replay is enabled. An unknown tariff or an unavailable capability is not permission to assume free access. The Console reads this contract through its server-side organisation scope; API secrets are never returned to your browser. Changing keys refreshes permissions and stops the previous connection. The API candidate publishes its market-data OpenAPI contract at /stream/openapi.json and the interactive reference at /docs/market-data. Internal ingestion and Console administration routes are excluded. On-chain customer routes are omitted when the corresponding release flags are disabled.

Run a signed connection

This example requires the release-candidate destinations to be enabled for your environment and organisation. It uses Node.js 22 or above with no dependencies. Run it on your backend, with a WebSockets key (ws_stream, stream.read) whose selected stream families are enabled. Your secret signs the grant request and is never sent to the feed. Save the connection example as polymarket-feed.mjs, then set BRAVADO_API_KEY and BRAVADO_API_SECRET in your environment. Run:
The example requests all four families and prints real received frames for 60 seconds. For collateral and resolutions only, set BRAVADO_EVENT_FAMILIES=collateral,resolutions. To test the separate fills socket, set BRAVADO_FEED_MODE=fills. No trades or on-chain operations are submitted. Quiet families may produce no events during a short observation. Sign the canonical path: query keys are sorted and values use RFC 3986 percent encoding. In this single-parameter example, the commas are encoded as %2C:
For staging, set both BRAVADO_API_ORIGIN and BRAVADO_FEED_ORIGIN to that environment. Do not exchange a staging grant against the production edge. Never paste a secret or a token into a support message. A 404 on /ws/onchain means that route has not been deployed there; it is not fixed by rotating a key. A 403 during grant issuance requires checking scope, family grants, plan and available credits. Reconnect with a new signed grant after expiry or a gap.

Recent replay

When capabilities report replay available, add "replay": 100 to the subscription message or replay=100 to the initial connection query. The candidate retains the latest 500 transitions across all families, reconstructed from its local durable retained journal on restart. Verified local-cache retirement can leave fewer than 500 transitions available after a restart; the current implementation does not load old bucket objects into the live replay buffer. The requested count is applied to transitions matching your subscriptions; overlapping subscriptions do not duplicate a transition. Replay frames carry replay: true. A nonbillable replay_end control reports requested, delivered, retained_transitions, earliest_cursor and barrier_cursor. The replay/live barrier prevents a new live publication from being interleaved with that replay. A queue overflow closes the connection. This bounded replay does not certify recovery of every missed event. Fewer matching transitions than requested may be available. Use the historical endpoint for older windows, subject to its separate permission and coverage status. An unsupported replay request fails explicitly instead of silently appearing to recover a gap.

Streams

Native condition IDs are kept at their ABI width in payloads. The existing 32-byte channel boundary right-pads native IDs with zero bytes. A condition filter does not include group-level converts without that condition ID.

Interpret amounts and identity

Amounts, token IDs, payout numerators and masks are exact decimal strings. Keep them as strings or integers; do not parse them as floating-point numbers.
  • Split and merge amounts describe the operation, not exchange volume.
  • Redemption amount is the payout, including zero. Native redemption also preserves position_amount; the two quantities are different.
  • Convert preserves neg_risk_market_id for CTF NegRisk, or native_event_id and condition_index for Protocol V2. Neither is a CTF condition ID.
  • CTF resolution payout is numerator divided by payout_denominator. Native module results use their verified denominator, not an assumed binary winner.
  • wallet is the on-chain initiator/stakeholder/redeemer. Native frames also preserve recipients. It is not automatically the owner EOA or transaction sender.
  • Asset address and verified decimals are explicit. Parent-position units must not be labelled as dollars. Missing metadata stays unknown.
These lifecycle logs alone do not reconstruct wallet balances. Transfers and fills also change balances, and related adapter/CTF logs must not be summed as independent economic flows.

Provenance and corrections

Schema version 2 carries event_id, event_version, chain, contract/ABI version, block hash, transaction, log index and decoded payload. Full mode also includes raw topics/data; compact mode omits those raw fields. It also carries venue_membership; unknown is not certified Polymarket membership. The occurrence identity includes the block hash. A reorg produces an explicit reorged transition with removed: true. Re-inclusion has a new occurrence ID. A finalization transition confirms the canonical occurrence. Free live corrections carry identity and state only, with delivery_kind: "correction"; they omit the economic payload and raw ABI fields. Merge them into a previously received event by event_id, applying a newer event_version. If you did not receive the initial event, keep its economic fields unknown and retrieve them through granted history. Requested replay supplies the full selected event shape and remains billable, including replayed finalization or reorg transitions. Deduplicate by (event_id, event_version), never by (tx_hash, status) for these families. Overlapping firehose, wallet and market subscriptions deliver an occurrence once per connection. The stream label uses the first matching route in deterministic order: firehose, condition, wallet, then group/token. Recent replay and historical queries remain release-gated; neither implies complete reconnect recovery or certified historical coverage.

Compact frame examples

These seven examples are synthetic fixtures with invented addresses, IDs and blocks. They document the candidate compact wire shape; they are not production observations or audited economic flows. Full mode adds raw ABI topics/data.

Historical REST candidate

The candidate route is GET /v1/polymarket/onchain/events, using the existing signed partner request format and independent history grants. Supply UTC from and to values and selected families. Windows are [from,to), limited to 31 days; limit defaults to 500 and cannot exceed 1,000. Optional wallet, condition_id and neg_risk_market_id filters combine with AND. consistency=finalized is the default. Pagination uses an opaque signed cursor bound to your organisation, filters and insertion snapshot. Pages follow UTC block timestamp, block number, transaction index and log index, with occurrence ID as a deterministic tie-breaker. Identifiers are not used as a substitute for execution order inside a block. While certification is pending, requests must explicitly use allow_partial=true; otherwise the candidate returns HISTORY_AUDIT_PENDING. A partial result always reports coverage.complete=false. It is not evidence of deployment-to-present coverage. Historical delivery uses the same bytes tariff and existing credit balance. Set format=ndjson to download one page as application/x-ndjson. The first line is export_metadata with next_cursor, coverage and billing; following lines contain the decoded events. The page has at most 1,000 events, default 500. Every line ends with a newline. Follow the signed cursor with the same filters until next_cursor is null. Changing the presentation between JSON and NDJSON preserves the same filter-bound cursor; changing the filters or organisation is rejected. Metadata and newline bytes are included in the delivered-byte charge. Console provides the same download through a session-checked HMAC bridge, with 100 events per page. Your API secret stays on the server. Select UTC start and exclusive end dates and the event families. Each download is a billable request; API delivery to Console is accounted even if your browser subsequently fails to save the file. This is a paginated download, not a background export job. Example first line (cursor abbreviated; use the actual signed cursor):
Background export jobs, complete-range certificates and durable archive-backed WebSocket replay remain separate release gates. Download availability does not certify dataset completeness.

Usage and price

The selected initial tariff is one credit per 20,000 uncompressed UTF-8 bytes of delivered data. It uses your existing credit balance. No separate monthly subscription is required. The access response must expose the effective tariff; unknown tariff is not free usage. Requested replay and historical downloads are billable deliveries. Controls, heartbeats, live identity-only finalization/correction frames and internal receipt retries are not charged. Requested replayed transitions are delivered data and are charged even when their event status is finalized or reorged. A generated but undelivered export is not a delivered-data charge. The candidate ledger records each streamed family separately: collateral, resolutions, new conditions and token registrations. Console Usage shows delivered credits by product. Failed or ambiguous writes retain their reservation for reconciliation; they do not automatically become a charge or a zero-byte settlement. Repeating an identical delivery receipt does not add consumption. These paths have finite acceptance tests; production invoice acceptance and the customer browser journey remain release gates.

Storage and recovery

Local capture files are a cache of the durable archive. The retention candidate removes only closed segments after byte-for-byte bucket verification, committed API index confirmation and recorded finality. It preserves bucket objects and the occurrence index; it does not shorten the historical API’s coverage by deleting historical records. Cache retirement is separate from coverage certification. It cannot prove that every contract, event family or block was captured. A lost or lagging index can be rebuilt from verified archive manifests with a finite repair budget; the same source identity and contiguous cursors are required. Older missing data is never silently replaced by a new starting cursor. These operations remain under release acceptance. Their internal credentials and storage permissions are not granted to a customer WebSockets key.

Coverage and availability

The historical goal is deployment-to-present coverage for the supported contracts and versions. Until backfill and independent reconciliation finish, no complete-history claim is made. A quiet event family can be healthy; evaluate block/index watermarks and coverage rather than the time of the last redemption. The capture candidate pins proxy ABI epochs by block and global log index. An uncertified upgrade halts the dataset checkpoint instead of extending the old ABI. A failed capture refuses new on-chain connections and closes existing sessions with CAPTURE_UNAVAILABLE during its bounded access recheck. Legacy fill access is a separate flow. General availability requires an independently reconciled finalized test day, stream-consumer comparison, recovery tests, price/usage reconciliation and a real self-service signup journey. Release-candidate UI and local fixture tests are not evidence that these criteria passed in production.

Feed status and uptime

Open the live operational status to inspect the current feed instance. This public, read-only endpoint returns 200 while capture is healthy and has committed a block within 30 seconds. It returns 503 while starting, stale or failed, and 404 before the managed on-chain route is enabled. Responses are not cached.
The sample is illustrative. Times ending in _ms are Unix milliseconds; uptime is seconds since this service instance started, not a historical SLA percentage. Capture progress is published only after the block’s durable journal commit. Before the first observed block, capture fields are null, not zero. A healthy live status does not certify complete historical coverage or venue attribution.