Skip to content

Payload Schema

Every webhook delivery carries a JSON body whose shape is defined by the Metrics Catalog. The catalog is the single source of truth — this page describes the wrapping shape and points to the catalog for field-level details.

Envelope

json { "schema_version": "v1", "event": "advice_cycle", "subscription_id": "sub_…", "delivered_at": "2026-05-06T12:34:56Z", "data": { "positions": [ /* one entry per position */ ], "market": { /* global market context */ } } }

Field Description
schema_version Matches CATALOG_VERSION. Bumps in lockstep with the catalog.
event What triggered the delivery (advice_cycle, out_of_range, …).
subscription_id The subscription this delivery belongs to.
delivered_at Server-side ISO-8601 timestamp at the moment of dispatch.
data The catalog-driven payload — see below.

data.positions[i]

Each position object flattens the position group at the top, then nests every other position-scope group under its name:

```json { "position_id": 12345, "token_pair": "USDC/WETH", "chain": "Ethereum", "...": "(other position-group fields)",

"pool": { / pool group fields / }, "similar_pools": [ / zero or more similar-pool items / ], "range_analysis": { / range_analysis group fields / } } ```

If a pool snapshot is unavailable for a position (e.g. brand-new pool not yet indexed), pool is emitted as {} rather than omitted.

range_analysis and market use omit-on-null semantics — a key whose value is unavailable is omitted from the payload entirely. Every other group emits null for missing nullable fields.

data.market

A single object shared across all positions in the payload:

json { "eth": { "price_usd": 3210.4, "change_24h_pct": 1.2, "...": "..." }, "btc": { "price_usd": 64210.0, "change_24h_pct": -0.4, "...": "..." }, "sentiment": { "fear_greed_index": 52, "classification": "Neutral" } }

Field-level documentation for every key is in the Metrics Catalog.