{
  "components": {
    "schemas": {
      "AddReconciledSetMemberRequest": {
        "description": "Request body for adding a wallet to your set.",
        "properties": {
          "wallet_address": {
            "description": "0x-prefixed 42-character hex Polygon address.",
            "title": "Wallet Address",
            "type": "string"
          }
        },
        "required": [
          "wallet_address"
        ],
        "title": "AddReconciledSetMemberRequest",
        "type": "object"
      },
      "AnalyzerInterpretationRequest": {
        "description": "Inputs to an analyzer-interpretation request.\n\nAll numeric fields are optional because the analyzer can\nlegitimately emit nulls when there are too few resolved\npositions. The service picks a safe fallback when a field is\nmissing; it rejects (422) only when a field is present but\nnon-finite (NaN or +/- inf).",
        "properties": {
          "brier": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Average Brier score (lower is better).",
            "title": "Brier"
          },
          "concentration_pct": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Share of realized PnL from the wallet's largest event, expressed as a percentage (e.g. 42.5 for 42.5%).",
            "title": "Concentration Pct"
          },
          "conviction_percentile": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Conviction (concentration) pillar percentile, 0-100.",
            "title": "Conviction Percentile"
          },
          "discipline_percentile": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Discipline (position count) pillar percentile, 0-100.",
            "title": "Discipline Percentile"
          },
          "edge_score": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Overall V3b composite, 0-100.",
            "title": "Edge Score"
          },
          "n_positions": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Count of resolved unique positions.",
            "title": "N Positions"
          },
          "oversizing_kelly": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Average actual size / reference Kelly fraction.",
            "title": "Oversizing Kelly"
          },
          "posture_percentile": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Posture (calibration) pillar percentile, 0-100.",
            "title": "Posture Percentile"
          },
          "total_pnl_usd": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Realized PnL in USD (positive or negative).",
            "title": "Total Pnl Usd"
          }
        },
        "title": "AnalyzerInterpretationRequest",
        "type": "object"
      },
      "AnalyzerInterpretationResponse": {
        "properties": {
          "fallback_used": {
            "title": "Fallback Used",
            "type": "boolean"
          },
          "generated_at": {
            "title": "Generated At",
            "type": "string"
          },
          "interpretation": {
            "title": "Interpretation",
            "type": "string"
          },
          "model": {
            "title": "Model",
            "type": "string"
          }
        },
        "required": [
          "interpretation",
          "model",
          "generated_at",
          "fallback_used"
        ],
        "title": "AnalyzerInterpretationResponse",
        "type": "object"
      },
      "ApiUsageResponse": {
        "description": "Current-UTC-day quota consumption for the calling key.\n\nReports the same counter the reservation RPC enforces (migration 142),\nread through the RPC's own no-op path so the number can never disagree\nwith the gate. This is the visibility half of usage metering: a caller\ncan see consumption before hitting the 429, and a dashboard can render\nit without scraping error responses.",
        "properties": {
          "plan": {
            "description": "Plan tier of the calling key.",
            "title": "Plan",
            "type": "string"
          },
          "usage_date": {
            "description": "UTC date (YYYY-MM-DD) the counters cover; resets at 00:00 UTC.",
            "title": "Usage Date",
            "type": "string"
          },
          "wallets_cap": {
            "description": "The key's daily reservation ceiling: the per-customer override when one is provisioned, otherwise the plan default.",
            "title": "Wallets Cap",
            "type": "integer"
          },
          "wallets_remaining": {
            "description": "max(0, wallets_cap - wallets_used); 0 means further reads 429 today.",
            "title": "Wallets Remaining",
            "type": "integer"
          },
          "wallets_used": {
            "description": "Wallet reads reserved against this key's daily quota so far today, across the verdict, batch, and reconciled-read endpoints. Counts reservations, not distinct wallets: the same address re-requested is re-counted, and a rejected batch reserves nothing.",
            "title": "Wallets Used",
            "type": "integer"
          }
        },
        "required": [
          "plan",
          "usage_date",
          "wallets_used",
          "wallets_cap",
          "wallets_remaining"
        ],
        "title": "ApiUsageResponse",
        "type": "object"
      },
      "CoherencePayload": {
        "properties": {
          "condition_id": {
            "title": "Condition Id",
            "type": "string"
          },
          "intra_market_arb_pp": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Intra Market Arb Pp"
          },
          "last_signal_emitted_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Signal Emitted At"
          },
          "n_signals_last_30d": {
            "default": 0,
            "minimum": 0.0,
            "title": "N Signals Last 30D",
            "type": "integer"
          },
          "n_signals_resolved_ambiguous": {
            "default": 0,
            "minimum": 0.0,
            "title": "N Signals Resolved Ambiguous",
            "type": "integer"
          },
          "n_signals_resolved_clean": {
            "default": 0,
            "minimum": 0.0,
            "title": "N Signals Resolved Clean",
            "type": "integer"
          },
          "snapshot_ts": {
            "title": "Snapshot Ts",
            "type": "string"
          }
        },
        "required": [
          "condition_id",
          "snapshot_ts"
        ],
        "title": "CoherencePayload",
        "type": "object"
      },
      "CommitForecastRequest": {
        "description": "Request body for registering a forecast commitment.",
        "properties": {
          "commitment_hash": {
            "description": "SHA-256 hex over canonical_json({'payload': payload, 'salt': salt}) per the published canonicalization rules (sorted keys, no whitespace, decimals as strings).",
            "title": "Commitment Hash",
            "type": "string"
          },
          "market_id": {
            "description": "Venue-canonical market identifier (condition_id or slug for Polymarket).",
            "maxLength": 200,
            "minLength": 1,
            "title": "Market Id",
            "type": "string"
          },
          "venue": {
            "description": "Lowercase venue slug, e.g. 'polymarket', 'kalshi', 'manifold'.",
            "title": "Venue",
            "type": "string"
          }
        },
        "required": [
          "venue",
          "market_id",
          "commitment_hash"
        ],
        "title": "CommitForecastRequest",
        "type": "object"
      },
      "CommitForecastResponse": {
        "description": "Server-timestamped commitment receipt.",
        "properties": {
          "commitment_hash": {
            "description": "The submitted hash, echoed.",
            "title": "Commitment Hash",
            "type": "string"
          },
          "commitment_id": {
            "title": "Commitment Id",
            "type": "string"
          },
          "committed_at": {
            "description": "Server-clock receipt timestamp.",
            "title": "Committed At",
            "type": "string"
          },
          "disclaimer": {
            "description": "Fixed; cannot be disabled.",
            "title": "Disclaimer",
            "type": "string"
          },
          "market_id": {
            "title": "Market Id",
            "type": "string"
          },
          "methodology_version": {
            "title": "Methodology Version",
            "type": "string"
          },
          "previous_row_hash": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Chain link of the previous ledger row; null at genesis.",
            "title": "Previous Row Hash"
          },
          "receipt": {
            "additionalProperties": {
              "type": "string"
            },
            "description": "Canonical receipt fields; receipt_hash is the SHA-256 of exactly this document's canonical serialization.",
            "title": "Receipt",
            "type": "object"
          },
          "receipt_hash": {
            "title": "Receipt Hash",
            "type": "string"
          },
          "row_hash": {
            "description": "Ledger chain link for this row.",
            "title": "Row Hash",
            "type": "string"
          },
          "venue": {
            "title": "Venue",
            "type": "string"
          }
        },
        "required": [
          "commitment_id",
          "venue",
          "market_id",
          "commitment_hash",
          "committed_at",
          "receipt",
          "receipt_hash",
          "row_hash",
          "previous_row_hash",
          "methodology_version",
          "disclaimer"
        ],
        "title": "CommitForecastResponse",
        "type": "object"
      },
      "CreateCheckoutRequest": {
        "description": "Request body for creating a Stripe Checkout session.",
        "properties": {
          "attribution": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "string"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "First-touch acquisition attribution (source / utm_* / referrer) captured client-side from the cvx_attr cookie. Carried into the Stripe checkout + subscription metadata so a converting customer is attributable to a channel. Whitelisted + length-capped before it reaches Stripe; optional (absent for direct/untagged sessions).",
            "title": "Attribution"
          },
          "billing_period": {
            "default": "monthly",
            "description": "Billing period: monthly or annual",
            "pattern": "^(monthly|annual)$",
            "title": "Billing Period",
            "type": "string"
          },
          "cancel_url": {
            "description": "URL to redirect if user cancels",
            "title": "Cancel Url",
            "type": "string"
          },
          "plan": {
            "description": "Target plan: researcher, trader, or enterprise (current); lite or pro accepted for legacy subscription portal flows",
            "pattern": "^(lite|pro|researcher|trader|enterprise)$",
            "title": "Plan",
            "type": "string"
          },
          "success_url": {
            "description": "URL to redirect on successful payment",
            "title": "Success Url",
            "type": "string"
          }
        },
        "required": [
          "plan",
          "success_url",
          "cancel_url"
        ],
        "title": "CreateCheckoutRequest",
        "type": "object"
      },
      "CreateCheckoutResponse": {
        "description": "Response containing the Checkout session URL.",
        "properties": {
          "checkout_url": {
            "title": "Checkout Url",
            "type": "string"
          }
        },
        "required": [
          "checkout_url"
        ],
        "title": "CreateCheckoutResponse",
        "type": "object"
      },
      "CreateKeyRequest": {
        "description": "Request body for generating a new API key.",
        "properties": {
          "label": {
            "default": "default",
            "description": "Human-readable label",
            "maxLength": 100,
            "minLength": 1,
            "title": "Label",
            "type": "string"
          }
        },
        "title": "CreateKeyRequest",
        "type": "object"
      },
      "CreatePortalRequest": {
        "description": "Request body for creating a Customer Portal session.",
        "properties": {
          "return_url": {
            "description": "URL to redirect back to after the portal session",
            "title": "Return Url",
            "type": "string"
          }
        },
        "required": [
          "return_url"
        ],
        "title": "CreatePortalRequest",
        "type": "object"
      },
      "CreatePortalResponse": {
        "description": "Response containing the Customer Portal session URL.",
        "properties": {
          "portal_url": {
            "title": "Portal Url",
            "type": "string"
          }
        },
        "required": [
          "portal_url"
        ],
        "title": "CreatePortalResponse",
        "type": "object"
      },
      "ForecastStatusResponse": {
        "description": "Public commitment status. Payload is never present before reveal.",
        "properties": {
          "commitment_hash": {
            "title": "Commitment Hash",
            "type": "string"
          },
          "commitment_id": {
            "title": "Commitment Id",
            "type": "string"
          },
          "committed_at": {
            "title": "Committed At",
            "type": "string"
          },
          "disclaimer": {
            "description": "Fixed; cannot be disabled.",
            "title": "Disclaimer",
            "type": "string"
          },
          "market_id": {
            "title": "Market Id",
            "type": "string"
          },
          "methodology_version": {
            "title": "Methodology Version",
            "type": "string"
          },
          "outcome": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Outcome"
          },
          "previous_row_hash": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Previous Row Hash"
          },
          "receipt_hash": {
            "title": "Receipt Hash",
            "type": "string"
          },
          "resolved_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Resolved At"
          },
          "reveal_failure_reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reveal Failure Reason"
          },
          "reveal_valid": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reveal Valid"
          },
          "revealed_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Revealed At"
          },
          "revealed_payload": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Present only after reveal; a revealed forecast record is public by design.",
            "title": "Revealed Payload"
          },
          "row_hash": {
            "title": "Row Hash",
            "type": "string"
          },
          "status": {
            "enum": [
              "committed",
              "revealed"
            ],
            "title": "Status",
            "type": "string"
          },
          "venue": {
            "title": "Venue",
            "type": "string"
          }
        },
        "required": [
          "commitment_id",
          "status",
          "venue",
          "market_id",
          "commitment_hash",
          "committed_at",
          "receipt_hash",
          "row_hash",
          "previous_row_hash",
          "revealed_at",
          "reveal_valid",
          "reveal_failure_reason",
          "revealed_payload",
          "resolved_at",
          "outcome",
          "methodology_version",
          "disclaimer"
        ],
        "title": "ForecastStatusResponse",
        "type": "object"
      },
      "FromFeaturesRequest": {
        "description": "Inputs to a feature-based Edge Score request.",
        "properties": {
          "concentration": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "V4 conviction input: bounded [0, 1] share of the wallet's GROSS winnings from its single largest event, i.e. clip(biggest_event_pnl / total_payoff, 0, 1). Values above the cap of 1.0 are clipped. Null or negative triggers median imputation and flags `used_median_concentration`. NOTE: this is NOT the legacy net-PnL ratio biggest_event_pct_of_total.",
            "title": "Concentration"
          },
          "n_positions": {
            "description": "Count of resolved positions. Must be >= 0. Callers should independently gate display on a minimum (typically >= 5) because pillar weights were fit on >=5-position wallets.",
            "minimum": 0.0,
            "title": "N Positions",
            "type": "integer"
          },
          "skill_brier": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Baseline Brier minus observed Brier. Positive values mean the wallet beats its own marginal frequency. Null or NaN triggers median imputation and the response flags `used_median_skill`.",
            "title": "Skill Brier"
          }
        },
        "required": [
          "n_positions"
        ],
        "title": "FromFeaturesRequest",
        "type": "object"
      },
      "FromWalletRequest": {
        "description": "Inputs to a wallet-based Edge Score request.",
        "properties": {
          "wallet_address": {
            "description": "Polymarket proxy wallet address (0x-prefixed, 42 chars).",
            "examples": [
              "0x56687bf447db6ffa42ffe2204a05edaa20f55839"
            ],
            "title": "Wallet Address",
            "type": "string"
          }
        },
        "required": [
          "wallet_address"
        ],
        "title": "FromWalletRequest",
        "type": "object"
      },
      "FullHistoryRequest": {
        "description": "Request body: the wallet to run the deep full-history read on.",
        "properties": {
          "wallet_address": {
            "description": "Polymarket proxy wallet address (0x-prefixed, 42 chars).",
            "title": "Wallet Address",
            "type": "string"
          }
        },
        "required": [
          "wallet_address"
        ],
        "title": "FullHistoryRequest",
        "type": "object"
      },
      "HTTPValidationError": {
        "properties": {
          "detail": {
            "items": {
              "$ref": "#/components/schemas/ValidationError"
            },
            "title": "Detail",
            "type": "array"
          }
        },
        "title": "HTTPValidationError",
        "type": "object"
      },
      "KalshiImportRequest": {
        "properties": {
          "csv_text": {
            "description": "Raw CSV text as exported from kalshi.com portfolio page. Flexible parser handles common column-name variants.",
            "maxLength": 5000000,
            "minLength": 1,
            "title": "Csv Text",
            "type": "string"
          },
          "dry_run": {
            "default": false,
            "description": "If True, parse and transform trades but skip the Supabase write. The response includes a preview list so the caller can verify the parse before committing.",
            "title": "Dry Run",
            "type": "boolean"
          }
        },
        "required": [
          "csv_text"
        ],
        "title": "KalshiImportRequest",
        "type": "object"
      },
      "KalshiImportResponse": {
        "properties": {
          "decisions_written": {
            "title": "Decisions Written",
            "type": "integer"
          },
          "dry_run": {
            "default": false,
            "title": "Dry Run",
            "type": "boolean"
          },
          "message": {
            "title": "Message",
            "type": "string"
          },
          "preview": {
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "title": "Preview",
            "type": "array"
          },
          "resolved_count": {
            "title": "Resolved Count",
            "type": "integer"
          },
          "trades_fetched": {
            "title": "Trades Fetched",
            "type": "integer"
          }
        },
        "required": [
          "trades_fetched",
          "decisions_written",
          "resolved_count",
          "message"
        ],
        "title": "KalshiImportResponse",
        "type": "object"
      },
      "KalshiResolveResponse": {
        "description": "Phase 2 response: counts from a Kalshi resolution sync run.",
        "properties": {
          "checked": {
            "title": "Checked",
            "type": "integer"
          },
          "errors": {
            "title": "Errors",
            "type": "integer"
          },
          "message": {
            "title": "Message",
            "type": "string"
          },
          "resolved_failure": {
            "title": "Resolved Failure",
            "type": "integer"
          },
          "resolved_success": {
            "title": "Resolved Success",
            "type": "integer"
          },
          "still_active": {
            "title": "Still Active",
            "type": "integer"
          }
        },
        "required": [
          "checked",
          "resolved_success",
          "resolved_failure",
          "still_active",
          "errors",
          "message"
        ],
        "title": "KalshiResolveResponse",
        "type": "object"
      },
      "KellyReplayRequest": {
        "description": "Request body: wallet + fractional-Kelly multipliers to simulate.",
        "properties": {
          "address": {
            "description": "Polymarket proxy wallet address (0x-prefixed, 42 chars).",
            "title": "Address",
            "type": "string"
          },
          "fractions": {
            "anyOf": [
              {
                "items": {
                  "type": "number"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Kelly fractions to simulate. Defaults to [0.25, 0.5, 1.0]. Each entry must be in (0, 2].",
            "title": "Fractions"
          }
        },
        "required": [
          "address"
        ],
        "title": "KellyReplayRequest",
        "type": "object"
      },
      "ManipulationPayload": {
        "properties": {
          "condition_id": {
            "title": "Condition Id",
            "type": "string"
          },
          "detector_run_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Detector Run At"
          },
          "insider_share_pct": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Insider Share Pct"
          },
          "snapshot_date": {
            "title": "Snapshot Date",
            "type": "string"
          },
          "total_volume_usd": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Total Volume Usd"
          },
          "wash_share_ci_high": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Wash Share Ci High"
          },
          "wash_share_ci_low": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Wash Share Ci Low"
          },
          "wash_share_ci_method": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Wash Share Ci Method"
          },
          "wash_share_n_units": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Wash Share N Units"
          },
          "wash_share_pct": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Wash Share Pct"
          },
          "wash_share_small_sample": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Wash Share Small Sample"
          }
        },
        "required": [
          "condition_id",
          "snapshot_date"
        ],
        "title": "ManipulationPayload",
        "type": "object"
      },
      "MarketIntegrityResponse": {
        "properties": {
          "canary_preview": {
            "default": true,
            "title": "Canary Preview",
            "type": "boolean"
          },
          "concentration": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Concentration"
          },
          "concentration_ex_infra": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Concentration Ex Infra"
          },
          "condition_id": {
            "title": "Condition Id",
            "type": "string"
          },
          "generated_at": {
            "title": "Generated At",
            "type": "string"
          },
          "method_hash": {
            "title": "Method Hash",
            "type": "string"
          },
          "note": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Note"
          },
          "round_trip_churn": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Round Trip Churn"
          },
          "source": {
            "title": "Source",
            "type": "string"
          },
          "venue": {
            "title": "Venue",
            "type": "string"
          }
        },
        "required": [
          "condition_id",
          "venue",
          "generated_at",
          "source",
          "method_hash"
        ],
        "title": "MarketIntegrityResponse",
        "type": "object"
      },
      "MarketSnapshotPayload": {
        "description": "Inbound shape for snapshot data on the recompute stub.\n\nRequired: condition_id, venue, snapshot_date, snapshot_ts.\nAll other fields are optional; the engine handles None gracefully.",
        "properties": {
          "category": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Category"
          },
          "condition_id": {
            "title": "Condition Id",
            "type": "string"
          },
          "days_to_resolution": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Days To Resolution"
          },
          "depth_no_at_ask_usd": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Depth No At Ask Usd"
          },
          "depth_no_at_bid_usd": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Depth No At Bid Usd"
          },
          "depth_yes_at_ask_usd": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Depth Yes At Ask Usd"
          },
          "depth_yes_at_bid_usd": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Depth Yes At Bid Usd"
          },
          "end_date": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "End Date"
          },
          "intra_market_arb_pp": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Intra Market Arb Pp"
          },
          "liquidity_usd": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Liquidity Usd"
          },
          "mid_price_no": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Mid Price No"
          },
          "mid_price_yes": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Mid Price Yes"
          },
          "question_text": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Question Text"
          },
          "resolution_risk_factors": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Resolution Risk Factors"
          },
          "resolution_risk_score": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Resolution Risk Score"
          },
          "snapshot_date": {
            "title": "Snapshot Date",
            "type": "string"
          },
          "snapshot_ts": {
            "title": "Snapshot Ts",
            "type": "string"
          },
          "source_artifact_hash": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Source Artifact Hash"
          },
          "source_artifact_path": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Source Artifact Path"
          },
          "spread_no_pp": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Spread No Pp"
          },
          "spread_yes_pp": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Spread Yes Pp"
          },
          "venue": {
            "default": "polymarket",
            "title": "Venue",
            "type": "string"
          },
          "volume_usd_24h": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Volume Usd 24H"
          }
        },
        "required": [
          "condition_id",
          "snapshot_date",
          "snapshot_ts"
        ],
        "title": "MarketSnapshotPayload",
        "type": "object"
      },
      "NotificationPreferences": {
        "description": "User notification preference settings.",
        "properties": {
          "monthly_summary": {
            "default": true,
            "title": "Monthly Summary",
            "type": "boolean"
          },
          "review_reminders": {
            "default": true,
            "title": "Review Reminders",
            "type": "boolean"
          },
          "streak_milestones": {
            "default": true,
            "title": "Streak Milestones",
            "type": "boolean"
          },
          "weekly_digest": {
            "default": true,
            "title": "Weekly Digest",
            "type": "boolean"
          }
        },
        "title": "NotificationPreferences",
        "type": "object"
      },
      "OwnerVerification": {
        "description": "Public owner-claim status for a wallet.\n\nReflects only rows the owner explicitly made public\n(cross_venue_identities.is_public = true); private claims are never\nexposed through this API.",
        "properties": {
          "claimed": {
            "description": "A public owner-claim row exists for this wallet.",
            "title": "Claimed",
            "type": "boolean"
          },
          "verification_expires_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Verification expiry (90 days after verified_at).",
            "title": "Verification Expires At"
          },
          "verified": {
            "description": "The public claim is signature-verified (EIP-4361 LINKED or CERTIFIED tier) and the verification has not expired.",
            "title": "Verified",
            "type": "boolean"
          },
          "verified_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Timestamp of the verifying signature.",
            "title": "Verified At"
          }
        },
        "required": [
          "claimed",
          "verified"
        ],
        "title": "OwnerVerification",
        "type": "object"
      },
      "ParticipantRollupPayload": {
        "properties": {
          "bottom_quartile_share_pct": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Bottom Quartile Share Pct"
          },
          "condition_id": {
            "title": "Condition Id",
            "type": "string"
          },
          "flagged_share_pct": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Flagged Share Pct"
          },
          "median_edge_score": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Median Edge Score"
          },
          "methodology_version": {
            "default": "edge_score_v3b",
            "title": "Methodology Version",
            "type": "string"
          },
          "n_trades": {
            "default": 0,
            "minimum": 0.0,
            "title": "N Trades",
            "type": "integer"
          },
          "n_unique_wallets": {
            "default": 0,
            "minimum": 0.0,
            "title": "N Unique Wallets",
            "type": "integer"
          },
          "snapshot_date": {
            "title": "Snapshot Date",
            "type": "string"
          },
          "top_quartile_share_pct": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Top Quartile Share Pct"
          },
          "total_volume_usd": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Total Volume Usd"
          },
          "venue": {
            "default": "polymarket",
            "title": "Venue",
            "type": "string"
          },
          "weighted_edge_score": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Weighted Edge Score"
          },
          "window_days": {
            "default": 30,
            "minimum": 1.0,
            "title": "Window Days",
            "type": "integer"
          }
        },
        "required": [
          "condition_id",
          "snapshot_date"
        ],
        "title": "ParticipantRollupPayload",
        "type": "object"
      },
      "PolymarketConnectRequest": {
        "properties": {
          "dry_run": {
            "default": false,
            "description": "If True, fetch and transform trades but skip the Supabase write. The response includes a preview list so the caller can verify the transform against any wallet (including whale wallets they don't own) without polluting their decisions table.",
            "title": "Dry Run",
            "type": "boolean"
          },
          "label": {
            "anyOf": [
              {
                "maxLength": 100,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional human-readable label for the wallet.",
            "title": "Label"
          },
          "wallet_address": {
            "description": "42-character Polygon wallet address (0x-prefixed hex).",
            "examples": [
              "0x1234567890123456789012345678901234567890"
            ],
            "title": "Wallet Address",
            "type": "string"
          }
        },
        "required": [
          "wallet_address"
        ],
        "title": "PolymarketConnectRequest",
        "type": "object"
      },
      "PolymarketConnectResponse": {
        "properties": {
          "decisions_written": {
            "title": "Decisions Written",
            "type": "integer"
          },
          "dry_run": {
            "default": false,
            "title": "Dry Run",
            "type": "boolean"
          },
          "message": {
            "title": "Message",
            "type": "string"
          },
          "preview": {
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "title": "Preview",
            "type": "array"
          },
          "resolved_count": {
            "title": "Resolved Count",
            "type": "integer"
          },
          "trades_fetched": {
            "title": "Trades Fetched",
            "type": "integer"
          },
          "wallet_address": {
            "title": "Wallet Address",
            "type": "string"
          }
        },
        "required": [
          "wallet_address",
          "trades_fetched",
          "decisions_written",
          "resolved_count",
          "message"
        ],
        "title": "PolymarketConnectResponse",
        "type": "object"
      },
      "PolymarketPublicPreviewRequest": {
        "properties": {
          "wallet_address": {
            "description": "42-character Polygon wallet address (0x-prefixed hex). No authentication required \u2014 this endpoint is public so unauthenticated visitors from social media links can try the product before signing up.",
            "examples": [
              "0x56687bf447db6ffa42ffe2204a05edaa20f55839"
            ],
            "title": "Wallet Address",
            "type": "string"
          }
        },
        "required": [
          "wallet_address"
        ],
        "title": "PolymarketPublicPreviewRequest",
        "type": "object"
      },
      "PolymarketPublicPreviewResponse": {
        "properties": {
          "message": {
            "title": "Message",
            "type": "string"
          },
          "preview": {
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "title": "Preview",
            "type": "array"
          },
          "trades_fetched": {
            "title": "Trades Fetched",
            "type": "integer"
          },
          "wallet_address": {
            "title": "Wallet Address",
            "type": "string"
          }
        },
        "required": [
          "wallet_address",
          "trades_fetched",
          "message"
        ],
        "title": "PolymarketPublicPreviewResponse",
        "type": "object"
      },
      "PolymarketResolveResponse": {
        "description": "Phase 2 response: counts from a resolution sync run.",
        "properties": {
          "checked": {
            "title": "Checked",
            "type": "integer"
          },
          "errors": {
            "title": "Errors",
            "type": "integer"
          },
          "message": {
            "title": "Message",
            "type": "string"
          },
          "resolved_failure": {
            "title": "Resolved Failure",
            "type": "integer"
          },
          "resolved_success": {
            "title": "Resolved Success",
            "type": "integer"
          },
          "still_active": {
            "title": "Still Active",
            "type": "integer"
          }
        },
        "required": [
          "checked",
          "resolved_success",
          "resolved_failure",
          "still_active",
          "errors",
          "message"
        ],
        "title": "PolymarketResolveResponse",
        "type": "object"
      },
      "RecomputeRequest": {
        "description": "Inputs for a recompute stub call.\n\nAll four layer dicts are pre-shaped; this is intentional so the\nengine can be exercised without a Supabase round-trip. The cron\nthat ships later will read these from Supabase / disk and call\n`build_card` directly without touching this endpoint.",
        "properties": {
          "coherence": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/CoherencePayload"
              },
              {
                "type": "null"
              }
            ]
          },
          "manipulation": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ManipulationPayload"
              },
              {
                "type": "null"
              }
            ]
          },
          "notes": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Notes"
          },
          "prev_card_hash": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Prev Card Hash"
          },
          "rollup": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ParticipantRollupPayload"
              },
              {
                "type": "null"
              }
            ]
          },
          "snapshot": {
            "$ref": "#/components/schemas/MarketSnapshotPayload"
          }
        },
        "required": [
          "snapshot"
        ],
        "title": "RecomputeRequest",
        "type": "object"
      },
      "ReconciledReadMember": {
        "description": "The caller's membership record for the requested wallet.",
        "properties": {
          "added_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "When the wallet joined the set.",
            "title": "Added At"
          },
          "last_read_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "When this member's most recent read completed. Null means it has never been read, which is never treated as up to date.",
            "title": "Last Read At"
          },
          "next_refresh_due_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "When the worker next re-reads this member.",
            "title": "Next Refresh Due At"
          },
          "read_state": {
            "description": "Where this member sits in the refresh lifecycle: queued (waiting for its turn), running (a read is in flight), ready (a read has landed), failed (the last attempt did not finish; it retries on its own schedule), or not_scoreable (TERMINAL: we could not produce a full-history read for this wallet that meets the conditions this set requires, nothing further is queued for it, and it does not consume a wallet slot). Set by the refresh worker, never by you. Any state this API does not recognize reports as queued.",
            "enum": [
              "queued",
              "running",
              "ready",
              "failed",
              "not_scoreable"
            ],
            "title": "Read State",
            "type": "string"
          },
          "refresh_days": {
            "description": "Your plan's refresh cadence in days. Staleness is derived from this plus last_read_at; it is deliberately not duplicated as a server-computed label so the rule has exactly one definition.",
            "title": "Refresh Days",
            "type": "integer"
          }
        },
        "required": [
          "read_state",
          "added_at",
          "last_read_at",
          "next_refresh_due_at",
          "refresh_days"
        ],
        "title": "ReconciledReadMember",
        "type": "object"
      },
      "ReconciledSetAddResponse": {
        "description": "Response for a successful add.",
        "properties": {
          "count": {
            "description": "Wallets in your set after this add.",
            "title": "Count",
            "type": "integer"
          },
          "limit": {
            "description": "Your plan's wallet cap at the time of this add.",
            "title": "Limit",
            "type": "integer"
          },
          "member": {
            "$ref": "#/components/schemas/ReconciledSetMember"
          }
        },
        "required": [
          "member",
          "limit",
          "count"
        ],
        "title": "ReconciledSetAddResponse",
        "type": "object"
      },
      "ReconciledSetListResponse": {
        "description": "The caller's full set, plus the plan context needed to render it.",
        "properties": {
          "can_add": {
            "description": "True when count is below limit AND total is below total_limit.",
            "title": "Can Add",
            "type": "boolean"
          },
          "count": {
            "description": "Wallets in your set that CONSUME your allowance. Since 2026-08-10 this excludes members whose read_state is not_scoreable: we cannot produce a number for them, so they do not spend a slot. Use `total` for the raw row count.",
            "title": "Count",
            "type": "integer"
          },
          "limit": {
            "description": "Your plan's wallet cap (including any entitlement override).",
            "title": "Limit",
            "type": "integer"
          },
          "members": {
            "items": {
              "$ref": "#/components/schemas/ReconciledSetMember"
            },
            "title": "Members",
            "type": "array"
          },
          "not_counted": {
            "description": "Members present but not consuming a slot (total minus count).",
            "title": "Not Counted",
            "type": "integer"
          },
          "plan": {
            "description": "Plan tier of the calling key.",
            "title": "Plan",
            "type": "string"
          },
          "refresh_days": {
            "description": "Your plan's refresh cadence in days.",
            "title": "Refresh Days",
            "type": "integer"
          },
          "rolling_window": {
            "$ref": "#/components/schemas/RollingWindow",
            "description": "The separate rate governing how fast NEW addresses may be taken on, and where you currently sit in it. Always present, so this rule can be read and paced against before an add is refused by it; its `usage` is null when your position could not be read."
          },
          "total": {
            "description": "All members, whatever their state, including not_scoreable.",
            "title": "Total",
            "type": "integer"
          },
          "total_limit": {
            "description": "The maximum number of member rows you may hold, whatever their state: twice your wallet cap. Exempting unreadable wallets from `count` would otherwise let a set accumulate them without bound, and each one costs a real chain read to diagnose.",
            "title": "Total Limit",
            "type": "integer"
          }
        },
        "required": [
          "plan",
          "limit",
          "count",
          "total",
          "not_counted",
          "total_limit",
          "can_add",
          "refresh_days",
          "rolling_window",
          "members"
        ],
        "title": "ReconciledSetListResponse",
        "type": "object"
      },
      "ReconciledSetMember": {
        "description": "One wallet in the caller's set, with its lifecycle + staleness state.",
        "properties": {
          "added_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "When the wallet joined your set.",
            "title": "Added At"
          },
          "last_read_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "When this member's most recent read completed. Null means it has never been read, which is never treated as up to date.",
            "title": "Last Read At"
          },
          "next_refresh_due_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "When the worker next re-reads this member.",
            "title": "Next Refresh Due At"
          },
          "read_age_days": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Days since the last read. Null when there has never been one.",
            "title": "Read Age Days"
          },
          "read_staleness": {
            "description": "Cadence-relative freshness of last_read_at. A member that has never been read is always overdue, never fresh.",
            "enum": [
              "fresh",
              "due",
              "overdue"
            ],
            "title": "Read Staleness",
            "type": "string"
          },
          "read_state": {
            "description": "Where this member sits in the refresh lifecycle: queued (waiting for its turn), running (a read is in flight), ready (a read has landed), failed (the last attempt did not finish; it retries on its own schedule), or not_scoreable (TERMINAL: we could not produce a full-history read for this wallet that meets the conditions this set requires, nothing further is queued for it, and it does not consume a wallet slot). Set by the refresh worker, never by you.",
            "enum": [
              "queued",
              "running",
              "ready",
              "failed",
              "not_scoreable"
            ],
            "title": "Read State",
            "type": "string"
          },
          "refresh_days": {
            "description": "Your plan's refresh cadence in days.",
            "title": "Refresh Days",
            "type": "integer"
          },
          "wallet_address": {
            "description": "Normalized (lowercased) wallet address.",
            "title": "Wallet Address",
            "type": "string"
          }
        },
        "required": [
          "wallet_address",
          "read_state",
          "added_at",
          "last_read_at",
          "next_refresh_due_at",
          "refresh_days",
          "read_staleness",
          "read_age_days"
        ],
        "title": "ReconciledSetMember",
        "type": "object"
      },
      "ReconciledSetRemoveResponse": {
        "description": "Response for a successful removal.",
        "properties": {
          "success": {
            "title": "Success",
            "type": "boolean"
          },
          "wallet_address": {
            "description": "Normalized (lowercased) wallet address.",
            "title": "Wallet Address",
            "type": "string"
          }
        },
        "required": [
          "success",
          "wallet_address"
        ],
        "title": "ReconciledSetRemoveResponse",
        "type": "object"
      },
      "RevealForecastRequest": {
        "description": "Request body for revealing a committed forecast.",
        "properties": {
          "payload": {
            "additionalProperties": true,
            "description": "The exact forecast payload that was hashed at commit time. Required fields: venue, market_id, probability (decimal string in [0, 1]). Extra disclosure fields are preserved.",
            "title": "Payload",
            "type": "object"
          },
          "salt": {
            "description": "The client salt used at commit time (min 16 chars).",
            "maxLength": 128,
            "minLength": 16,
            "title": "Salt",
            "type": "string"
          }
        },
        "required": [
          "payload",
          "salt"
        ],
        "title": "RevealForecastRequest",
        "type": "object"
      },
      "RevealForecastResponse": {
        "description": "Reveal verdict: hash recomputation result.",
        "properties": {
          "commitment_hash": {
            "title": "Commitment Hash",
            "type": "string"
          },
          "commitment_id": {
            "title": "Commitment Id",
            "type": "string"
          },
          "committed_at": {
            "title": "Committed At",
            "type": "string"
          },
          "disclaimer": {
            "description": "Fixed; cannot be disabled.",
            "title": "Disclaimer",
            "type": "string"
          },
          "methodology_version": {
            "title": "Methodology Version",
            "type": "string"
          },
          "recomputed_hash": {
            "title": "Recomputed Hash",
            "type": "string"
          },
          "reveal_failure_reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reveal Failure Reason"
          },
          "reveal_valid": {
            "title": "Reveal Valid",
            "type": "boolean"
          },
          "revealed_at": {
            "title": "Revealed At",
            "type": "string"
          },
          "status": {
            "const": "revealed",
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "commitment_id",
          "status",
          "reveal_valid",
          "reveal_failure_reason",
          "commitment_hash",
          "recomputed_hash",
          "committed_at",
          "revealed_at",
          "methodology_version",
          "disclaimer"
        ],
        "title": "RevealForecastResponse",
        "type": "object"
      },
      "ReviewPreScreenRequest": {
        "description": "An assembled pre-screen prompt (built by the web spine).",
        "properties": {
          "system": {
            "maxLength": 8000,
            "minLength": 10,
            "title": "System",
            "type": "string"
          },
          "user": {
            "maxLength": 24000,
            "minLength": 10,
            "title": "User",
            "type": "string"
          }
        },
        "required": [
          "system",
          "user"
        ],
        "title": "ReviewPreScreenRequest",
        "type": "object"
      },
      "ReviewPreScreenResponse": {
        "description": "Raw model completion text. The web spine parses + contract-checks it.",
        "properties": {
          "text": {
            "title": "Text",
            "type": "string"
          }
        },
        "required": [
          "text"
        ],
        "title": "ReviewPreScreenResponse",
        "type": "object"
      },
      "RollingWindow": {
        "description": "The rate at which NEW addresses may be taken on, and this account's\nposition in it.\n\nA different bound from the wallet cap. The cap limits how many wallets are\nkept current at once and is reported by `limit` and `count`; this limits\nhow fast new ones are taken on, because an address never read before costs\na complete on-chain walk. Removing a wallet is free and immediate against\nboth, and re-adding an address this account has held before draws on\nneither.",
        "properties": {
          "allowance": {
            "description": "Distinct new addresses admitted per window. Resolved for this account when `usage` is present; resolved from the plan tier alone when `usage` is null, which can differ from the enforced figure where a bespoke rate applies.",
            "title": "Allowance",
            "type": "integer"
          },
          "usage": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/RollingWindowUsage"
              },
              {
                "type": "null"
              }
            ],
            "description": "Position in the window, or null when it could not be read. Null means UNKNOWN, never a full allowance and never a spent one: the rule above still stands and adds are still enforced against it."
          },
          "window_days": {
            "description": "Length of the trailing window, in days.",
            "title": "Window Days",
            "type": "integer"
          }
        },
        "required": [
          "window_days",
          "allowance",
          "usage"
        ],
        "title": "RollingWindow",
        "type": "object"
      },
      "RollingWindowUsage": {
        "description": "Where this account currently sits inside its rolling allowance.",
        "properties": {
          "first_fill_remaining": {
            "description": "Distinct addresses that can still be added before the allowance binds at all. While this is above zero the rate is not in force, because the account is still filling the set its plan covers, and `remaining` describes a rule that is not yet applying. Reported by the database, never derived from the other counts: whether an add consumed one of these turns on facts about the address that no other field here carries.",
            "title": "First Fill Remaining",
            "type": "integer"
          },
          "remaining": {
            "description": "New addresses that can still be taken on before an add is refused with `wallet_set_window_limit_reached`. Never negative. Not a statement about any particular address: re-adding one this account has held before is exempt and costs none of this.",
            "title": "Remaining",
            "type": "integer"
          },
          "resets_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "When the oldest add counted against the window ages out and one unit of `remaining` returns. Null when nothing is currently counted against the window.",
            "title": "Resets At"
          },
          "used": {
            "description": "Distinct new addresses taken on inside the trailing window. May exceed `allowance` after a plan change that lowered the rate; `remaining` is zero in that case and never negative.",
            "title": "Used",
            "type": "integer"
          }
        },
        "required": [
          "used",
          "remaining",
          "first_fill_remaining",
          "resets_at"
        ],
        "title": "RollingWindowUsage",
        "type": "object"
      },
      "SetEntitlementRequest": {
        "description": "Stamp a per-customer entitlement override (migration 143).\n\nAll three numeric caps are REQUIRED (the NOT-NULL-on-insert convention): a\nNULL cap floors to the researcher level at read time, so an admin who\nomitted one would silently under-provision. Requiring all three turns\n\"forgot a column\" into a rejected request, not a wrong cap.",
        "properties": {
          "batch_cap": {
            "description": "Per-batch distinct-wallet cap.",
            "minimum": 0.0,
            "title": "Batch Cap",
            "type": "integer"
          },
          "daily_verdict_quota": {
            "description": "Per-UTC-day wallet-verdict quota override.",
            "minimum": 0.0,
            "title": "Daily Verdict Quota",
            "type": "integer"
          },
          "notes": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Deal reference.",
            "title": "Notes"
          },
          "package": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Display/audit label.",
            "title": "Package"
          },
          "rescore_cadence": {
            "default": "monthly",
            "description": "Only 'monthly' is deliverable today.",
            "title": "Rescore Cadence",
            "type": "string"
          },
          "user_id": {
            "description": "Customer's auth.users id.",
            "title": "User Id",
            "type": "string"
          },
          "wallet_cap": {
            "description": "Watchlist breadth override.",
            "minimum": 0.0,
            "title": "Wallet Cap",
            "type": "integer"
          }
        },
        "required": [
          "user_id",
          "wallet_cap",
          "daily_verdict_quota",
          "batch_cap"
        ],
        "title": "SetEntitlementRequest",
        "type": "object"
      },
      "SubscriptionResponse": {
        "description": "Current subscription information.",
        "properties": {
          "cancel_at_period_end": {
            "default": false,
            "title": "Cancel At Period End",
            "type": "boolean"
          },
          "current_period_end": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Current Period End"
          },
          "plan": {
            "title": "Plan",
            "type": "string"
          },
          "status": {
            "title": "Status",
            "type": "string"
          },
          "subscription_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Subscription Id"
          }
        },
        "required": [
          "plan",
          "status"
        ],
        "title": "SubscriptionResponse",
        "type": "object"
      },
      "SyncSubscriptionResponse": {
        "description": "Result of the self-healing subscription sync (2026-06-10).",
        "properties": {
          "plan": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Plan"
          },
          "subscription_status": {
            "title": "Subscription Status",
            "type": "string"
          },
          "synced": {
            "title": "Synced",
            "type": "boolean"
          }
        },
        "required": [
          "synced",
          "plan",
          "subscription_status"
        ],
        "title": "SyncSubscriptionResponse",
        "type": "object"
      },
      "ValidationError": {
        "properties": {
          "ctx": {
            "title": "Context",
            "type": "object"
          },
          "input": {
            "title": "Input"
          },
          "loc": {
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "integer"
                }
              ]
            },
            "title": "Location",
            "type": "array"
          },
          "msg": {
            "title": "Message",
            "type": "string"
          },
          "type": {
            "title": "Error Type",
            "type": "string"
          }
        },
        "required": [
          "loc",
          "msg",
          "type"
        ],
        "title": "ValidationError",
        "type": "object"
      },
      "WalletAnalysisFeatures": {
        "description": "Inputs lifted from the Polymarket wallet analyzer response.\n\nThe analyzer already computes everything we need to build a rough\nforward simulation: the wallet's historical category win rate is a\nproxy for per-position probability; n_unique_positions is the portfolio\nbreadth; total_risked is the starting bankroll; kelly_sizing efficiency\nis the oversizing multiplier applied to each decision's payoff spread.\n\nClients (the analyzer page) should post the fields they have. Missing\nor invalid fields get safe defaults so the simulation still runs.",
        "properties": {
          "address": {
            "description": "Polymarket wallet address (0x-prefixed).",
            "title": "Address",
            "type": "string"
          },
          "avg_stake_pct": {
            "anyOf": [
              {
                "maximum": 1.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Mean fraction of bankroll per position.",
            "title": "Avg Stake Pct"
          },
          "concentration": {
            "anyOf": [
              {
                "maximum": 1.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Biggest event pct-of-total. Drives tail risk.",
            "title": "Concentration"
          },
          "kelly_sizing_efficiency": {
            "anyOf": [
              {
                "maximum": 10.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "actual_fraction / kelly_fraction ratio.",
            "title": "Kelly Sizing Efficiency"
          },
          "n_iterations": {
            "default": 10000,
            "maximum": 100000.0,
            "minimum": 1000.0,
            "title": "N Iterations",
            "type": "integer"
          },
          "n_unique_positions": {
            "anyOf": [
              {
                "maximum": 100.0,
                "minimum": 1.0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Deduped positions used to size the portfolio.",
            "title": "N Unique Positions"
          },
          "seed": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Seed"
          },
          "skill_brier": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Baseline - actual Brier. Positive = skilled.",
            "title": "Skill Brier"
          },
          "total_risked": {
            "anyOf": [
              {
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Total USD risked across resolved history.",
            "title": "Total Risked"
          },
          "win_rate": {
            "anyOf": [
              {
                "maximum": 1.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Realized win rate across resolved positions.",
            "title": "Win Rate"
          }
        },
        "required": [
          "address"
        ],
        "title": "WalletAnalysisFeatures",
        "type": "object"
      },
      "WalletAnalysisRequest": {
        "description": "Request body: just the wallet address.",
        "properties": {
          "source_surface": {
            "anyOf": [
              {
                "maxLength": 128,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Client surface that initiated the analysis, for funnel analytics.",
            "title": "Source Surface"
          },
          "utm_campaign": {
            "anyOf": [
              {
                "maxLength": 128,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Utm Campaign"
          },
          "utm_medium": {
            "anyOf": [
              {
                "maxLength": 128,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Utm Medium"
          },
          "utm_source": {
            "anyOf": [
              {
                "maxLength": 128,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Utm Source"
          },
          "visitor_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Visitor Id"
          },
          "wallet_address": {
            "description": "Polymarket proxy wallet address (0x-prefixed, 42 chars).",
            "examples": [
              "0x56687bf447db6ffa42ffe2204a05edaa20f55839"
            ],
            "title": "Wallet Address",
            "type": "string"
          }
        },
        "required": [
          "wallet_address"
        ],
        "title": "WalletAnalysisRequest",
        "type": "object"
      },
      "WalletProofOfRecordResponse": {
        "description": "The portable record object for a wallet in the caller's set, or the\nexplicit withheld state naming the gate that stopped issuance.\n\nClaim guardrails, identical to the sibling read endpoints: the estimate\nonly ever appears inside a record that also carries its 95% interval and\nBOTH denominators; the ``edge_disclosure`` string restates them in one\nsentence; the disclaimer is fixed. When ``issued`` is false there is no\nrecord, no hash, and no number of any kind.",
        "properties": {
          "address": {
            "description": "Normalized (lowercased) wallet address.",
            "title": "Address",
            "type": "string"
          },
          "completeness_proof": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Verbatim echo of the read's chain-anchored proof block (see the reconciled-read endpoint). Packaging, not a verdict.",
            "title": "Completeness Proof"
          },
          "disclaimer": {
            "description": "Fixed; cannot be disabled.",
            "title": "Disclaimer",
            "type": "string"
          },
          "edge_disclosure": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The estimate, its 95% interval, and both denominators in one sentence. The record never travels as a bare number.",
            "title": "Edge Disclosure"
          },
          "generated_at": {
            "description": "When this object was generated (UTC ISO). The object's own as-of, alongside reconciled_at_block; neither stands in for the other.",
            "title": "Generated At",
            "type": "string"
          },
          "issued": {
            "description": "True only when every issuance gate passed and a record object was built. False carries withheld_gate + withheld_detail and no numbers.",
            "title": "Issued",
            "type": "boolean"
          },
          "member": {
            "$ref": "#/components/schemas/ReconciledReadMember"
          },
          "method_version": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Hash of the frozen methodology the record was computed and gated under, same value the promotion gate enforces. Pin it to detect method changes between objects.",
            "title": "Method Version"
          },
          "reconciled_at_block": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "The Polygon block the record's completeness was checked against; the starting point of the chain check in verification. Null when issued is false, never 0.",
            "title": "Reconciled At Block"
          },
          "record": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "The exact field set the record hash covers: address, reconciled_at_block, reconciled_as_of, method_version, realized_edge, realized_edge_ci_bca, realized_edge_n, n_resolved_complete, n_priced, n_unpriced. Recompute the hash from this object with the served recipe; it must equal record_hash.",
            "title": "Record"
          },
          "record_hash": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "sha256:<hex> over the canonical JSON serialization of record (key-sorted, compact separators). Content-addresses this record so a copy can be checked for tampering offline.",
            "title": "Record Hash"
          },
          "verification": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Copyable third-party checks: chain_check_command (one curl against any Polygon archive RPC; empty results in both halves mean the address moved no outcome token after reconciled_at_block) and record_hash_recipe (recompute the hash from the served record with stdlib Python).",
            "title": "Verification"
          },
          "withheld_detail": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Fixed prose for the failing gate. Null when issued.",
            "title": "Withheld Detail"
          },
          "withheld_gate": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The FIRST failing issuance gate, in the payload's own vocabulary (e.g. not_reconciled, windowed, chain_stale, pricing_insufficient). Null when issued.",
            "title": "Withheld Gate"
          }
        },
        "required": [
          "address",
          "issued",
          "member",
          "generated_at",
          "disclaimer"
        ],
        "title": "WalletProofOfRecordResponse",
        "type": "object"
      },
      "WalletReconciledReadResponse": {
        "description": "On-chain-reconciled full-history read, or the honest unavailable state.\n\nClaim guardrails, identical to the verdict payload's: ``realized_edge`` is\nnever present without ``realized_edge_ci_bca``, the sub-sample bound\ntravels in the SAME string as the estimate (``edge_disclosure``, built by\nthe one shared formatter), and the disclaimer is fixed. When ``available``\nis false EVERY estimate field is null: a partial or windowed number is\nnever returned in place of a complete read.",
        "properties": {
          "address": {
            "description": "Normalized (lowercased) wallet address.",
            "title": "Address",
            "type": "string"
          },
          "available": {
            "description": "True only when a complete on-chain-reconciled read served.",
            "title": "Available",
            "type": "boolean"
          },
          "completeness_proof": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Chain-anchored completeness proof for this read: the basis, the reconciliation block and timestamp, the serve-time answer to whether the address moved an outcome token since that block, whether the read proved itself complete, and a verification instruction you can run against Polygon yourself. It echoes stamps this response already carries; the block of fields is packaging, not a verdict, and it is null when available is false.",
            "title": "Completeness Proof"
          },
          "disclaimer": {
            "description": "Fixed; cannot be disabled.",
            "title": "Disclaimer",
            "type": "string"
          },
          "edge_disclosure": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The edge, its 95% interval, and BOTH denominators (priced of complete resolved, plus the un-priceable remainder) in one string.",
            "title": "Edge Disclosure"
          },
          "member": {
            "$ref": "#/components/schemas/ReconciledReadMember"
          },
          "message": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Present when available is false.",
            "title": "Message"
          },
          "method_hash": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Hash of the frozen methodology this read was computed and gated under; the promotion gate checks the same value. Pin it to detect method changes between reads. Null when available is false.",
            "title": "Method Hash"
          },
          "n_priced": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Positions priced at their own entry fills.",
            "title": "N Priced"
          },
          "n_resolved_complete": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Markets resolved to completion.",
            "title": "N Resolved Complete"
          },
          "n_unpriced": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Positions counted but not priced (no entry price was recovered for them in this read).",
            "title": "N Unpriced"
          },
          "realized_edge": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Realized edge per priced position, on the probability scale. Never returned without realized_edge_ci_bca.",
            "title": "Realized Edge"
          },
          "realized_edge_ci_bca": {
            "anyOf": [
              {
                "items": {
                  "type": "number"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Event-clustered BCa 95% interval [lo, hi], paired with the edge.",
            "title": "Realized Edge Ci Bca"
          },
          "reconciled_as_of": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "When the reconciliation proof was taken.",
            "title": "Reconciled As Of"
          },
          "reconciled_at_block": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "The Polygon block this read's completeness was checked against: at that block the reconstructed record matched the wallet's on-chain settlement history in full. It exists so you can check currency yourself instead of taking it on trust: ask the chain whether this address moved an outcome token after this block, and if it did, the read no longer covers the whole record. It does NOT say the read is current now; it says where an independent currency check must start. Null when available is false, never 0.",
            "title": "Reconciled At Block"
          },
          "state": {
            "anyOf": [
              {
                "enum": [
                  "skilled",
                  "luck",
                  "insufficient",
                  "flagged"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Four-state read of the resolved record.",
            "title": "State"
          },
          "state_definition": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Fixed definition of the returned state.",
            "title": "State Definition"
          },
          "styles": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Descriptive style tags for HOW the edge is earned (arbitrage, concentrated, favorite_tilt, directional). Labels, never gates: a structural style does not demote the state, it discloses it.",
            "title": "Styles"
          },
          "unavailable_reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "'not_reconciled' when no complete read is available yet.",
            "title": "Unavailable Reason"
          }
        },
        "required": [
          "address",
          "available",
          "member",
          "disclaimer"
        ],
        "title": "WalletReconciledReadResponse",
        "type": "object"
      },
      "WalletScreenResponse": {
        "description": "Matches, plus the denominator they were drawn from.\n\n`screened` is the field that makes the rest interpretable. There are two\nwallet universes and they are not the same: the wallets Convexly has READ,\nand every wallet on the venue. This endpoint can only filter the first, so\nit publishes how many wallets the filter actually ran over. Without it, \"0\nmatches\" reads as a fact about the market rather than about our coverage.",
        "properties": {
          "has_more": {
            "title": "Has More",
            "type": "boolean"
          },
          "matched": {
            "description": "Wallets that matched, before the page cut.",
            "title": "Matched",
            "type": "integer"
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Pass as `after_wallet` for the next page.",
            "title": "Next Cursor"
          },
          "rows": {
            "items": {
              "$ref": "#/components/schemas/WalletScreenRow"
            },
            "title": "Rows",
            "type": "array"
          },
          "screened": {
            "description": "Wallets this filter ran over. The denominator, including wallets the filters excluded. NOT a count of every wallet that exists.",
            "title": "Screened",
            "type": "integer"
          },
          "universe": {
            "description": "What `screened` is a denominator of, in words.",
            "title": "Universe",
            "type": "string"
          }
        },
        "required": [
          "rows",
          "screened",
          "matched",
          "has_more",
          "universe"
        ],
        "title": "WalletScreenResponse",
        "type": "object"
      },
      "WalletScreenRow": {
        "description": "One matching wallet, carrying the same certification shape as the screen.",
        "properties": {
          "certification": {
            "additionalProperties": true,
            "title": "Certification",
            "type": "object"
          },
          "wallet": {
            "title": "Wallet",
            "type": "string"
          }
        },
        "required": [
          "wallet",
          "certification"
        ],
        "title": "WalletScreenRow",
        "type": "object"
      },
      "WalletVerdictBatchItem": {
        "description": "One address's result inside a batch response.",
        "properties": {
          "address": {
            "title": "Address",
            "type": "string"
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Present when ok is false.",
            "title": "Error"
          },
          "ok": {
            "description": "True when a verdict was computed.",
            "title": "Ok",
            "type": "boolean"
          },
          "verdict": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/WalletVerdictResponse"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "address",
          "ok"
        ],
        "title": "WalletVerdictBatchItem",
        "type": "object"
      },
      "WalletVerdictBatchRequest": {
        "description": "Request body for the batch verdict endpoint.",
        "properties": {
          "addresses": {
            "description": "Wallet addresses to score (0x + 40 hex). Deduplicated; the number of DISTINCT addresses must not exceed your plan's per-batch cap.",
            "items": {
              "type": "string"
            },
            "maxItems": 250,
            "minItems": 1,
            "title": "Addresses",
            "type": "array"
          }
        },
        "required": [
          "addresses"
        ],
        "title": "WalletVerdictBatchRequest",
        "type": "object"
      },
      "WalletVerdictBatchResponse": {
        "description": "Batch verdict response: one item per distinct requested address.",
        "properties": {
          "disclaimer": {
            "description": "Fixed; cannot be disabled.",
            "title": "Disclaimer",
            "type": "string"
          },
          "max_for_plan": {
            "description": "Per-batch distinct-address cap for this plan.",
            "title": "Max For Plan",
            "type": "integer"
          },
          "plan": {
            "description": "Plan tier of the calling key.",
            "title": "Plan",
            "type": "string"
          },
          "requested": {
            "description": "Distinct addresses requested.",
            "title": "Requested",
            "type": "integer"
          },
          "results": {
            "items": {
              "$ref": "#/components/schemas/WalletVerdictBatchItem"
            },
            "title": "Results",
            "type": "array"
          },
          "returned": {
            "description": "Addresses with a computed verdict.",
            "title": "Returned",
            "type": "integer"
          }
        },
        "required": [
          "requested",
          "returned",
          "plan",
          "max_for_plan",
          "results",
          "disclaimer"
        ],
        "title": "WalletVerdictBatchResponse",
        "type": "object"
      },
      "WalletVerdictResponse": {
        "description": "Verdict payload: state-machine outputs only, never prose judgments.\n\nConstraint (binding; this docstring is published in the public\nOpenAPI spec, so registry names stay out of it too): no dollar PnL\nfields, no external pre-registration registry IDs, and realized_edge\nis never present without realized_edge_ci_bca. Methodology links\nbelong on convexly.app/research, not in payloads.",
        "properties": {
          "address": {
            "description": "Normalized (lowercased) wallet address.",
            "title": "Address",
            "type": "string"
          },
          "as_of": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "When the on-chain reconciliation proof behind this read was taken. Null when no complete read is on file.",
            "title": "As Of"
          },
          "completeness_proof": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Chain-anchored completeness proof for this read: the basis, the reconciliation block and timestamp, the serve-time answer to whether the address moved an outcome token since that block, whether the read proved itself complete, and a verification instruction you can run against Polygon yourself. It echoes stamps this response already carries; the block of fields is packaging, not a verdict, and it is null when no complete read served.",
            "title": "Completeness Proof"
          },
          "concentration": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "biggest_event_pnl / net_realized_pnl. Not bounded to [0, 1]; null when not computable.",
            "title": "Concentration"
          },
          "disclaimer": {
            "description": "Fixed; cannot be disabled.",
            "title": "Disclaimer",
            "type": "string"
          },
          "edge_disclosure": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The edge, its 95% interval, and BOTH denominators (priced of complete resolved, plus the un-priceable remainder) in one string. Null when no complete read served.",
            "title": "Edge Disclosure"
          },
          "method_hash": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Hash of the frozen methodology this read was computed and gated under; the promotion gate checks the same value. Pin it to detect method changes between reads. Null when no complete read served.",
            "title": "Method Hash"
          },
          "methodology_version": {
            "title": "Methodology Version",
            "type": "string"
          },
          "n_priced": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Positions priced at their own entry fills; equals n_resolved (kept under both names so this payload and the reconciled-read payload can be diffed field for field). Null when no complete read served.",
            "title": "N Priced"
          },
          "n_resolved": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Resolved positions the edge and its interval were computed over. THIS IS THE PRICED SUBSET: the part of the complete resolved record for which an on-chain entry price was recoverable in this read. It is not the size of that record and is normally smaller than it; n_resolved_complete in this same response is that size, and n_priced repeats this count under the name the reconciled-read endpoint uses, so the two endpoints disclose the same denominators. A POSITIVE integer when a complete read served, and NULL when none did. Null means nothing here was counted, not that a count came to zero: the two are different claims and only one of them is something this API ever knows. Zero is not in the contract and is never emitted.",
            "title": "N Resolved"
          },
          "n_resolved_complete": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Markets resolved to completion in the full on-chain record: the denominator n_resolved is a subset of. Null when no complete read served.",
            "title": "N Resolved Complete"
          },
          "n_unpriced": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Positions counted but not priced (no entry price was recovered for them in this read). Null when no complete read served.",
            "title": "N Unpriced"
          },
          "owner_verified": {
            "$ref": "#/components/schemas/OwnerVerification"
          },
          "realized_edge": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Realized edge on the probability scale. Null whenever the BCa interval is unavailable; never returned alone.",
            "title": "Realized Edge"
          },
          "realized_edge_ci_bca": {
            "anyOf": [
              {
                "items": {
                  "type": "number"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "BCa bootstrap 95% interval [lo, hi]; paired with the edge.",
            "title": "Realized Edge Ci Bca"
          },
          "reconciled_at_block": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "The Polygon block this read's completeness was checked against: at that block the reconstructed record matched the wallet's on-chain settlement history in full. It exists so you can check currency yourself instead of taking it on trust: ask the chain whether this address moved an outcome token after this block, and if it did, the read no longer covers the whole record. It does NOT say the read is current now; it says where an independent currency check must start. Null when no complete read served, never 0.",
            "title": "Reconciled At Block"
          },
          "state": {
            "description": "Four-state badge machine output.",
            "enum": [
              "skilled",
              "luck",
              "insufficient",
              "flagged"
            ],
            "title": "State",
            "type": "string"
          },
          "state_definition": {
            "description": "Fixed definition of the returned state, with a style clause appended when a structural style is present.",
            "title": "State Definition",
            "type": "string"
          },
          "styles": {
            "description": "Descriptive style tags (2026-07-15 realized-edge reframe): how the edge is earned and its payoff shape (arbitrage / concentrated / favorite_tilt / directional). NEVER changes the state; a structural style on a skilled record means the edge is not forecasting. ['directional'] when no structural style fires.",
            "items": {
              "type": "string"
            },
            "title": "Styles",
            "type": "array"
          }
        },
        "required": [
          "address",
          "state",
          "state_definition",
          "realized_edge",
          "realized_edge_ci_bca",
          "n_resolved",
          "edge_disclosure",
          "n_resolved_complete",
          "n_priced",
          "n_unpriced",
          "concentration",
          "owner_verified",
          "as_of",
          "reconciled_at_block",
          "methodology_version",
          "disclaimer"
        ],
        "title": "WalletVerdictResponse",
        "type": "object"
      },
      "WebhookResponse": {
        "description": "Result of webhook processing.",
        "properties": {
          "status": {
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "status"
        ],
        "title": "WebhookResponse",
        "type": "object"
      }
    },
    "securitySchemes": {
      "APIKeyHeader": {
        "description": "Mint at https://convexly.app/settings. 32-byte hex token. Treat as a secret \u2014 anyone with the key has the same access as your account.",
        "in": "header",
        "name": "X-API-Key",
        "type": "apiKey"
      }
    }
  },
  "info": {
    "contact": {
      "name": "Convexly Engineering",
      "url": "https://convexly.app/docs/api"
    },
    "description": "Public REST surface for external integrations. Authentication is via the `X-API-Key` header; mint keys at https://convexly.app/settings. Available to Researcher / Trader / Team / Enterprise plans (and legacy Pro). \n\nThis is the customer-facing contract. Internal endpoints (admin, billing webhooks, cron handlers, AI-compute, market-trust card recompute) are NOT part of this surface and are subject to breaking change without notice. If you need an endpoint published here, file an issue rather than calling the unstable surface.",
    "license": {
      "name": "All rights reserved",
      "url": "https://convexly.app/terms"
    },
    "title": "Convexly Public API",
    "version": "0.1.0"
  },
  "openapi": "3.1.0",
  "paths": {
    "/api/v1/public/forecasts/commit": {
      "post": {
        "description": "Register a salted forecast hash before the outcome is knowable.\n\nConvexly stores the hash with a server-clock timestamp and returns a\nreceipt whose receipt_hash the issuer can recompute independently to\nprove what was attested. The forecast content itself is NOT\ntransmitted at commit time; it stays with the forecaster until\nreveal.",
        "operationId": "commit_forecast_api_v1_public_forecasts_commit_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CommitForecastRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CommitForecastResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "APIKeyHeader": []
          }
        ],
        "summary": "Register a forecast commitment (hash only)",
        "tags": [
          "public-api"
        ]
      }
    },
    "/api/v1/public/forecasts/{commitment_id}": {
      "get": {
        "description": "Read the public status of a commitment.\n\nBefore reveal only the hash, the market binding, the receipt fields,\nand the chain links are visible; the forecast payload is NEVER\nreturned before reveal. After reveal the payload is public by design;\nthat is what a public track record means.",
        "operationId": "get_forecast_status_api_v1_public_forecasts__commitment_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "commitment_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Commitment Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ForecastStatusResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [],
        "summary": "Public commitment status",
        "tags": [
          "public-api"
        ]
      }
    },
    "/api/v1/public/forecasts/{commitment_id}/reveal": {
      "post": {
        "description": "Reveal the payload + salt behind a commitment.\n\nThe server recomputes the canonical hash and stores the verdict:\nreveal_valid is true only when the recomputed hash equals the\ncommitted hash AND the payload's market binding matches the committed\nmarket AND the payload schema is valid. The reveal is single-shot and\npermanent: byte-identical re-reveals are idempotent (200 with the\nstored verdict); any different content is rejected with 409. An\ninvalid reveal is stored as evidence and cannot be replaced.",
        "operationId": "reveal_forecast_api_v1_public_forecasts__commitment_id__reveal_post",
        "parameters": [
          {
            "in": "path",
            "name": "commitment_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Commitment Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RevealForecastRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RevealForecastResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "APIKeyHeader": []
          }
        ],
        "summary": "Reveal a committed forecast (payload + salt)",
        "tags": [
          "public-api"
        ]
      }
    },
    "/api/v1/public/usage": {
      "get": {
        "description": "Report the calling key's wallet-read consumption for the current UTC day.\n\nCosts no quota. Reads through the reservation RPC's no-op branch so the\nreported number is the enforced number, never a parallel count that can\ndrift from it.",
        "operationId": "get_api_usage_api_v1_public_usage_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiUsageResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "security": [
          {
            "APIKeyHeader": []
          }
        ],
        "summary": "Current-day quota usage for the calling key",
        "tags": [
          "public-api"
        ]
      }
    },
    "/api/v1/public/wallets/reconciled-set": {
      "get": {
        "description": "List every wallet in the calling key owner's set.\n\nYour plan buys a bounded number of distinct wallets kept current on a\nper-tier cadence (see ``refresh_days``), not a number of reads. This\nalways returns 200, even for a plan or entitlement resolving to a cap of\nzero (``limit: 0, can_add: false``) -- listing your own resource state is\nnever refused, only adding past it is.\n\n``rolling_window`` reports the SECOND bound, which is a rate rather than a\nholding: how many distinct new addresses may be taken on per window, and\nhow much of that is left. Read it to pace adds rather than discovering the\nrate through a 429. Two things never draw on it, so neither shows up in\nthese counts: re-adding an address that has been in your set before, and\nany add made while ``usage.first_fill_remaining`` is above zero. Removing\na wallet is free against this rate and takes effect immediately.\n\n``rolling_window.usage`` is null when your position in the window could\nnot be read. That is UNKNOWN, not zero and not full; the rule beside it\nstill stands and adds are still enforced against it.",
        "operationId": "list_reconciled_set_api_v1_public_wallets_reconciled_set_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReconciledSetListResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "security": [
          {
            "APIKeyHeader": []
          }
        ],
        "summary": "List your wallet set",
        "tags": [
          "public-api"
        ]
      },
      "post": {
        "description": "Add one wallet to the calling key owner's set, enforcing the plan cap.\n\nChecked against the address format and lowercased before any write,\nexactly like every other wallet-address input in this module. The add is\nserialized through an advisory-locked database reservation, so\nconcurrent adds for the same owner -- across multiple keys, multiple\nprocesses, or a mix of this API and the dashboard -- cannot race past\nthe cap: the count-and-insert happens under one lock keyed on the owner.\n\nThe effective cap is your plan's default wallet allowance unless a\nbespoke per-customer override applies, resolved fail-closed exactly\nlike every other per-customer cap in this module (an override present\nbut blank floors to the researcher-tier cap, never your plan default\nand never the enterprise ceiling).\n\nReturns 409 for a wallet already in your set, or 403 for a set that has\nno room; both name the limit and (for the 403s) the current count so a\ncaller never has to make a second call to find out why. There are TWO\n403s with distinct codes: `wallet_set_cap_reached` when your allowance is\nfull, and `wallet_set_total_rows_reached` when your allowance has room\nbut the set is holding its maximum number of rows (which only happens by\naccumulating wallets that cannot be read).\n\nA THIRD refusal, `wallet_set_window_limit_reached`, is a 429 rather than a\n403 because it is a rate and not an entitlement: new addresses may be\ntaken on only so fast, since each one that has never been read before\ntriggers a complete on-chain walk. Two things never draw on that rate, and\nthe response says when the next slot frees up:\n\n* re-adding an address that has previously been in your set, however long\n  ago and whether or not its first read had finished; and\n* any add made while you are still filling the set for the first time, up\n  to your plan's wallet allowance.\n\nRemoving a wallet is always free and takes effect immediately. It costs no\npart of this rate and never has to be waited out.",
        "operationId": "add_reconciled_set_member_api_v1_public_wallets_reconciled_set_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddReconciledSetMemberRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReconciledSetAddResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "APIKeyHeader": []
          }
        ],
        "summary": "Add a wallet to your set",
        "tags": [
          "public-api"
        ]
      }
    },
    "/api/v1/public/wallets/reconciled-set/{address}": {
      "delete": {
        "description": "Remove one wallet from the calling key owner's set.\n\nScoped to the authenticated user id (the service role bypasses RLS, so\nthis filter IS the ownership gate, same posture as every other query in\nthis module): a wallet that is not in YOUR set is a 404 regardless of\nwhether it is in someone else's, and nothing about another customer's\nset is revealed by the response.\n\nRemoving a wallet does not consume or refund any quota; it only ever\nfrees a slot under your plan's cap. No concurrency primitive is needed\nhere (unlike the add path): two concurrent deletes of the same row are\nnaturally safe, since at most one of them can ever find a row to remove.",
        "operationId": "remove_reconciled_set_member_api_v1_public_wallets_reconciled_set__address__delete",
        "parameters": [
          {
            "in": "path",
            "name": "address",
            "required": true,
            "schema": {
              "title": "Address",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReconciledSetRemoveResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "APIKeyHeader": []
          }
        ],
        "summary": "Remove a wallet from your set",
        "tags": [
          "public-api"
        ]
      }
    },
    "/api/v1/public/wallets/screen": {
      "get": {
        "description": "Filter the wallets Convexly has read on chain, ordered by address.\n\nAnswers the question a caller actually has before spending a set slot:\nwhich wallets clear the floor, and which already carry a certified read.\nEvery response publishes `screened`, the number of wallets the filter ran\nover, because this endpoint can only screen wallets we have READ and a\ncaller must be able to tell that apart from a statement about the market.\n\n`min_resolved_positions` filters on the CHAIN count, not the venue trade\nwindow. Those are different quantities and neither bounds the other.\n\nPaging is keyset (`after_wallet`), not offset: the read lane writes\ncontinuously, so an offset would silently skip or repeat a wallet.\n\nGated on the same plan allowance as the set itself; a plan that cannot hold\nwallets cannot screen for them.",
        "operationId": "screen_wallets_api_v1_public_wallets_screen_get",
        "parameters": [
          {
            "in": "query",
            "name": "min_resolved_positions",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Min Resolved Positions"
            }
          },
          {
            "in": "query",
            "name": "certified",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "boolean"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Certified"
            }
          },
          {
            "in": "query",
            "name": "include_not_scoreable",
            "required": false,
            "schema": {
              "default": false,
              "title": "Include Not Scoreable",
              "type": "boolean"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 50,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "after_wallet",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "After Wallet"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WalletScreenResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "APIKeyHeader": []
          }
        ],
        "summary": "Screen the wallets we have read (filterable, with a denominator)",
        "tags": [
          "public-api"
        ]
      }
    },
    "/api/v1/public/wallets/verdict/batch": {
      "post": {
        "description": "Score up to a plan-capped number of distinct wallets in one call.\n\nSame per-wallet schema and claim guardrails as the single verdict\nendpoint. The number of DISTINCT addresses is capped by the calling\nkey's plan (BATCH_VERDICT_MAX_BY_PLAN), so no tier gets cohort-scale\naccess beyond what it paid for; exceeding the cap is a 403. Invalid\naddresses return a per-item error rather than failing the batch, and\nconcurrency is bounded so a large batch cannot stampede the upstream.",
        "operationId": "post_wallet_verdict_batch_api_v1_public_wallets_verdict_batch_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WalletVerdictBatchRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WalletVerdictBatchResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "APIKeyHeader": []
          }
        ],
        "summary": "Batch wallet skill verdicts (tier-capped)",
        "tags": [
          "public-api"
        ]
      }
    },
    "/api/v1/public/wallets/{address}/badge": {
      "get": {
        "description": "302 to the Next.js badge SVG so embedders get one stable URL family.\n\nNo API key required: the destination\n(https://www.convexly.app/api/badge/wallet/{address}) is itself\npublic and consent-gated. It renders a neutral tile (no verdict)\nunless the skill badge is enabled AND the wallet owner has\nsignature-claimed the wallet and made the claim public; only then\ndoes it render the compact non-attesting verdict tile. The same\nvocabulary as convexly.app/skill travels with the badge.\n\nArgs:\n    address: Polymarket wallet address (0x-prefixed, 42 chars).\n    style: Optional \"light\" for the light badge theme; any other\n        value falls through to the default dark theme downstream.",
        "operationId": "get_wallet_badge_api_v1_public_wallets__address__badge_get",
        "parameters": [
          {
            "in": "path",
            "name": "address",
            "required": true,
            "schema": {
              "title": "Address",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "style",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Style"
            }
          }
        ],
        "responses": {
          "302": {
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [],
        "summary": "Wallet badge (redirect to the embeddable SVG)",
        "tags": [
          "public-api"
        ]
      }
    },
    "/api/v1/public/wallets/{address}/proof-of-record": {
      "get": {
        "description": "Return the portable record object for a wallet in your set.\n\nThe object packages the on-chain-reconciled read's anchors into a\nthird-party-verifiable primitive: a canonical record subset, a sha256\ncontent hash over exactly that subset, the block anchor, the frozen\nmethod hash, and two copyable verification commands. The chain check is\nthe api-docs posture made executable: ask Polygon whether this address\nmoved an outcome token after reconciled_at_block; an empty answer is the\nclaim that the record is still complete, and no venue API response can\ncarry an equivalent check.\n\nFail-closed, in order: a plan with no wallet allowance is refused; a\nwallet outside your set is a 404 and costs no quota; and a read that\ndoes not clear every issuance gate (complete-read stamp, serve-time\nchain currency, pricing sufficiency, interval and denominators present,\nblock anchor, method hash) returns ``issued: false`` with the first\nfailing gate named. No partial object is ever issued.\n\nUsage is metered against the same per-key daily wallet quota as the\nother wallet-read endpoints, reserved AFTER the membership gate.",
        "operationId": "get_wallet_proof_of_record_api_v1_public_wallets__address__proof_of_record_get",
        "parameters": [
          {
            "in": "path",
            "name": "address",
            "required": true,
            "schema": {
              "title": "Address",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WalletProofOfRecordResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "APIKeyHeader": []
          }
        ],
        "summary": "Portable proof-of-record object (wallets in your set)",
        "tags": [
          "public-api"
        ]
      }
    },
    "/api/v1/public/wallets/{address}/reconciled-read": {
      "get": {
        "description": "Return the reconciled full-history read for a wallet in your set.\n\nYour plan buys a bounded set of distinct wallets kept current on a\nper-tier cadence, not a number of reads. This endpoint serves the read for\none member of that set; wallets outside it return 404.\n\nFail-closed, in order: a plan whose wallet allowance is zero is refused; a\nwallet the calling key's owner does not have in their set is a 404 and\ncosts no quota; and a wallet whose stored read does not prove complete\nreturns ``available: false`` with every estimate field null rather than the\nwindowed estimate.\n\nUsage is metered against the same per-key daily wallet quota as the verdict\nendpoints, reserved AFTER the membership gate so a 404 never spends it.",
        "operationId": "get_wallet_reconciled_read_api_v1_public_wallets__address__reconciled_read_get",
        "parameters": [
          {
            "in": "path",
            "name": "address",
            "required": true,
            "schema": {
              "title": "Address",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WalletReconciledReadResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "APIKeyHeader": []
          }
        ],
        "summary": "On-chain-reconciled full-history read (wallets in your set)",
        "tags": [
          "public-api"
        ]
      }
    },
    "/api/v1/public/wallets/{address}/verdict": {
      "get": {
        "description": "Return the four-state skill verdict for a Polymarket wallet.\n\nServed from the on-chain-reconciled record only. A wallet gets a state\nwhen a complete read has been reconciled for it and that read is still\ncurrent (nothing moved on chain since the block it was reconciled at);\notherwise the response is \"insufficient\" with both estimate fields null\nand a state_definition saying there is no current complete read. The\nstate itself is the binding badge machine mirrored from\napps/web/src/lib/skill-badge.ts via app/engine/skill_badge.py, run over\nthe complete resolved record at reconciliation time.\n\nUsage is metered: one public_verdict_served row per call with the\nsha256 of the API key id and of the wallet address (never the raw\nvalues).",
        "operationId": "get_wallet_verdict_api_v1_public_wallets__address__verdict_get",
        "parameters": [
          {
            "in": "path",
            "name": "address",
            "required": true,
            "schema": {
              "title": "Address",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WalletVerdictResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "APIKeyHeader": []
          }
        ],
        "summary": "Wallet skill verdict (four-state machine)",
        "tags": [
          "public-api"
        ]
      }
    }
  },
  "security": [
    {
      "APIKeyHeader": []
    }
  ],
  "servers": [
    {
      "description": "Production",
      "url": "https://www.convexly.app/api/engine"
    }
  ],
  "tags": []
}
