{"openapi":"3.1.0","info":{"title":"Circles Advanced Analytics","description":"Advanced analytics services for the Circles network","version":"2.0.0"},"servers":[{"url":"/analytics"}],"paths":{"/bot-analytics/classify":{"post":{"tags":["BotAnalytics"],"summary":"Classify Addresses","description":"Classify addresses for bot behavior\n\n- **address**: Single address to analyze\n- **addresses**: List of addresses to analyze\n- **use_classifier**: Override the use of ML classifier","operationId":"classify_addresses_bot_analytics_classify_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BotAnalyticsRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BotAnalyticsResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["BotAnalytics"],"summary":"Classify Address","description":"Classify a single address for bot behavior\n\n- **address**: Ethereum address to analyze\n- **use_classifier**: Override the use of ML classifier","operationId":"classify_address_bot_analytics_classify_get","parameters":[{"name":"address","in":"query","required":true,"schema":{"type":"string","description":"Ethereum address to analyze","title":"Address"},"description":"Ethereum address to analyze"},{"name":"use_classifier","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Override use of ML classifier","title":"Use Classifier"},"description":"Override use of ML classifier"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BotAnalyticsResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/bot-analytics/health":{"get":{"tags":["BotAnalytics"],"summary":"Health Check","description":"Check if the Bot Analytics service is healthy","operationId":"health_check_bot_analytics_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/bot-analytics/stats":{"get":{"tags":["BotAnalytics"],"summary":"Get Classification Stats","description":"Get classification statistics","operationId":"get_classification_stats_bot_analytics_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/bot-analytics/blacklist":{"get":{"tags":["BotAnalytics"],"summary":"List Blacklisted Addresses","description":"Return all blacklisted addresses.\n\n**Inputs (all optional):**\n- **include_reason** — include the reason string with each entry (default *true*).\n- **v2_only** — only return addresses registered as V2 avatars (default *false*).\n- **reasons** — filter to entries with these exact reason values. Pass multiple times for OR logic, e.g. ?reasons=puppet&reasons=duplicate_avatar.\n- **reason_contains** — filter to entries whose reason contains any of these substrings (OR logic). Pass multiple times, e.g. ?reason_contains=Puppets&reason_contains=deprecated_account.\n- **limit** / **offset** — pagination (max 10 000 per page).\n\n**Response:** *{ addresses: [...], total, count, v2_only }*.\nWhen **include_reason** is *true*, each entry is *{ address, reason }*. When *false*, entries are plain address strings.","operationId":"get_blacklist_bot_analytics_blacklist_get","parameters":[{"name":"include_reason","in":"query","required":false,"schema":{"type":"boolean","description":"Include reason for blacklisting","default":true,"title":"Include Reason"},"description":"Include reason for blacklisting"},{"name":"v2_only","in":"query","required":false,"schema":{"type":"boolean","description":"Only return addresses registered as V2 avatars.","default":false,"title":"V2 Only"},"description":"Only return addresses registered as V2 avatars."},{"name":"reasons","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by exact reason match (OR logic).","title":"Reasons"},"description":"Filter by exact reason match (OR logic)."},{"name":"reason_contains","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by reason substring match (OR logic). Pass multiple times for multiple patterns.","title":"Reason Contains"},"description":"Filter by reason substring match (OR logic). Pass multiple times for multiple patterns."},{"name":"limit","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":10000,"minimum":1},{"type":"null"}],"description":"Page size (max 10000)","title":"Limit"},"description":"Page size (max 10000)"},{"name":"offset","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"description":"Pagination offset","title":"Offset"},"description":"Pagination offset"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/bot-analytics/whitelist":{"get":{"tags":["BotAnalytics"],"summary":"List Whitelisted Addresses","description":"Return all whitelisted addresses.\n\n**Inputs (all optional):**\n- **include_reason** — include the reason string with each entry (default *true*).\n- **v2_only** — only return addresses registered as V2 avatars (default *false*).\n- **reasons** — filter to entries with these exact reason values. Pass multiple times for OR logic, e.g. ?reasons=invitation_bot&reasons=trusted_by_org.\n- **reason_contains** — filter to entries whose reason contains any of these substrings (OR logic). Pass multiple times, e.g. ?reason_contains=deprecated_account&reason_contains=test_account.\n- **limit** / **offset** — pagination (max 10 000 per page).\n\n**Response:** *{ addresses: [...], total, count, v2_only }*.\nWhen **include_reason** is *true*, each entry is *{ address, reason }*. When *false*, entries are plain address strings.","operationId":"get_whitelist_bot_analytics_whitelist_get","parameters":[{"name":"include_reason","in":"query","required":false,"schema":{"type":"boolean","description":"Include reason for whitelisting","default":true,"title":"Include Reason"},"description":"Include reason for whitelisting"},{"name":"v2_only","in":"query","required":false,"schema":{"type":"boolean","description":"Only return addresses registered as V2 avatars.","default":false,"title":"V2 Only"},"description":"Only return addresses registered as V2 avatars."},{"name":"reasons","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by exact reason match (OR logic).","title":"Reasons"},"description":"Filter by exact reason match (OR logic)."},{"name":"reason_contains","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by reason substring match (OR logic). Pass multiple times for multiple patterns.","title":"Reason Contains"},"description":"Filter by reason substring match (OR logic). Pass multiple times for multiple patterns."},{"name":"limit","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":10000,"minimum":1},{"type":"null"}],"description":"Page size (max 10000)","title":"Limit"},"description":"Page size (max 10000)"},{"name":"offset","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"description":"Pagination offset","title":"Offset"},"description":"Pagination offset"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/rep_score/health":{"get":{"tags":["Rep Score"],"summary":"Health","operationId":"health_rep_score_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}}}}},"/rep_score/config":{"get":{"tags":["Rep Score"],"summary":"Config Endpoint","description":"Service + per-group configuration in pipeline-staged form.\n\n`defaults` and each entry in `groups[].params` follow the same\npipeline layout as the avatar response (1:1 with the per-avatar\n`components` shape):\n\n  - `behaviour`   — weights, tau_days (R/Q/I), kappa (Q/I), eta, cold_start\n  - `propagation` — aggregation, alpha_young/mature, D_young, delta,\n                    solver {tol, max_iter}\n  - `boost.static`   — attestation `sources` list (drives B_static)\n  - `boost.network`  — legacy bilateral-trust knobs (threshold,\n                       count_cap, per_bilateral)\n  - `boost.delta`    — leaky-integrator knobs (mode, mu, tau_days,\n                       lambda_static, gamma, pos_matrix, neg_matrix,\n                       windowed_lookback_days)\n  - `composition` — mode, delta_placement, clip_score_user\n  - `gate`        — R2.2 cliff (window_hours, threshold_gcrc, penalty)\n  - `data`        — flow_lookback_days, excluded_addresses\n  - `history`     — write thresholds for the history table\n\nPer-avatar responses (`/avatars/{...}`, `/scores`, `/holdings`,\nhistory rows) carry only measured / computed values — every knob\nabove is read from here.","operationId":"config_endpoint_rep_score_config_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfigResponse"}}}}}}},"/rep_score/groups":{"get":{"tags":["Rep Score"],"summary":"Groups Endpoint","operationId":"groups_endpoint_rep_score_groups_get","parameters":[{"name":"include_variants","in":"query","required":false,"schema":{"type":"boolean","description":"If true, also include variant groups (entries where `default == false`). By default, only canonical entries (one per `group_address`) are returned.","default":false,"title":"Include Variants"},"description":"If true, also include variant groups (entries where `default == false`). By default, only canonical entries (one per `group_address`) are returned."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/rep_score/groups/{group_address}/scores":{"get":{"tags":["Rep Score"],"summary":"Group Scores","operationId":"group_scores_rep_score_groups__group_address__scores_get","parameters":[{"name":"group_address","in":"path","required":true,"schema":{"type":"string","description":"42-char 0x-prefixed group address (short group id also accepted for back-compat)","title":"Group Address"},"description":"42-char 0x-prefixed group address (short group id also accepted for back-compat)"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":10000,"minimum":1,"default":100,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"live","in":"query","required":false,"schema":{"type":"boolean","description":"If false, skip the live postgres lookup and zero-fill the live layer.","default":true,"title":"Live"},"description":"If false, skip the live postgres lookup and zero-fill the live layer."},{"name":"details","in":"query","required":false,"schema":{"type":"boolean","description":"If false, omit the `components` block (the full pipeline-staged decomposition: behaviour, propagation, boost, composition, gate) and return only the main scores: reputation_score, reputation_score_live, behaviour_score, boost_score, blacklisted, is_member.","default":true,"title":"Details"},"description":"If false, omit the `components` block (the full pipeline-staged decomposition: behaviour, propagation, boost, composition, gate) and return only the main scores: reputation_score, reputation_score_live, behaviour_score, boost_score, blacklisted, is_member."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupScoresResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/rep_score/groups/{group_address}/holdings":{"get":{"tags":["Rep Score"],"summary":"Group Holdings","description":"Per-avatar liquidity + flow rankings.\n\nSurfaces `balance`, `outstanding`, `B/O ratio`, and four-window\nflow aggregates (`window` = `flow_lookback_days` total, `last_day`,\n`last_24h`, `last_7d`) for every avatar in the group. Powers the\nHoldings tab on the dashboard.","operationId":"group_holdings_rep_score_groups__group_address__holdings_get","parameters":[{"name":"group_address","in":"path","required":true,"schema":{"type":"string","description":"42-char group address or short id","title":"Group Address"},"description":"42-char group address or short id"},{"name":"sort_by","in":"query","required":false,"schema":{"type":"string","description":"Sort field. balance | outstanding | bo_ratio | flows.<window>.<primitive>","default":"balance","title":"Sort By"},"description":"Sort field. balance | outstanding | bo_ratio | flows.<window>.<primitive>"},{"name":"order","in":"query","required":false,"schema":{"enum":["asc","desc"],"type":"string","default":"desc","title":"Order"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":5000,"minimum":1,"default":500,"title":"Limit"}},{"name":"include_non_members","in":"query","required":false,"schema":{"type":"boolean","description":"Include non-members in the ranking (defaults to true).","default":true,"title":"Include Non Members"},"description":"Include non-members in the ranking (defaults to true)."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HoldingsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/rep_score/groups/{group_address}/runs":{"get":{"tags":["Rep Score"],"summary":"Group Runs","description":"Recent refresh runs for a group — feeds the Runs tab and the\ndistribution-comparison picker.","operationId":"group_runs_rep_score_groups__group_address__runs_get","parameters":[{"name":"group_address","in":"path","required":true,"schema":{"type":"string","description":"42-char group address or short id","title":"Group Address"},"description":"42-char group address or short id"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":50,"title":"Limit"}},{"name":"flushed_only","in":"query","required":false,"schema":{"type":"boolean","description":"Only runs that persisted history rows (rows_scored > 0) — the ones a distribution comparison can read. Cache-only ticks and failed runs are excluded.","default":false,"title":"Flushed Only"},"description":"Only runs that persisted history rows (rows_scored > 0) — the ones a distribution comparison can read. Cache-only ticks and failed runs are excluded."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/rep_score/groups/{group_address}/runs/{run_id}/scores":{"get":{"tags":["Rep Score"],"summary":"Group Run Scores","description":"Every avatar's score as recorded by one past refresh run — the\nhistorical-distribution side of the score-distribution comparison.\n\nReads `rep_score_history` for the run; `reputation_score` is the\nunclipped surface (floor of s_user_raw), matching the live histogram.","operationId":"group_run_scores_rep_score_groups__group_address__runs__run_id__scores_get","parameters":[{"name":"group_address","in":"path","required":true,"schema":{"type":"string","description":"42-char group address or short id","title":"Group Address"},"description":"42-char group address or short id"},{"name":"run_id","in":"path","required":true,"schema":{"type":"string","description":"run_id from /runs","title":"Run Id"},"description":"run_id from /runs"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunScoresResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/rep_score/groups/{group_address}/provenance-history":{"get":{"tags":["Rep Score"],"summary":"Provenance History","description":"Timeline of distinct (algorithm_version, params_hash, snapshot_hash)\nfingerprints observed in `rep_score_history` for this group.\n\nEach item carries the time window over which a given config was in\neffect, plus the count of history rows / distinct avatars written\nunder it. Powers the overview tab's config-history panel — operators\nuse it to see when params or the legacy snapshot were rotated, and\nto spot the \"forgotten version bump\" case (same `algorithm_version`\nbut two distinct `params_hash` values).","operationId":"provenance_history_rep_score_groups__group_address__provenance_history_get","parameters":[{"name":"group_address","in":"path","required":true,"schema":{"type":"string","description":"42-char group address or short id","title":"Group Address"},"description":"42-char group address or short id"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProvenanceHistoryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/rep_score/groups/{group_address}/avatars/{address}":{"get":{"tags":["Rep Score"],"summary":"Avatar State","operationId":"avatar_state_rep_score_groups__group_address__avatars__address__get","parameters":[{"name":"group_address","in":"path","required":true,"schema":{"type":"string","description":"42-char 0x-prefixed group address (short group id also accepted for back-compat)","title":"Group Address"},"description":"42-char 0x-prefixed group address (short group id also accepted for back-compat)"},{"name":"address","in":"path","required":true,"schema":{"type":"string","title":"Address"}},{"name":"details","in":"query","required":false,"schema":{"type":"boolean","description":"If false, omit the `components` block (the full pipeline-staged decomposition: behaviour, propagation, boost, composition, gate). reputation_score, reputation_score_live, raw_score, behaviour_score, and boost_score are still returned.","default":true,"title":"Details"},"description":"If false, omit the `components` block (the full pipeline-staged decomposition: behaviour, propagation, boost, composition, gate). reputation_score, reputation_score_live, raw_score, behaviour_score, and boost_score are still returned."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AvatarStateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/rep_score/groups/{group_address}/avatars/{address}/flows":{"get":{"tags":["Rep Score"],"summary":"Avatar Flows","operationId":"avatar_flows_rep_score_groups__group_address__avatars__address__flows_get","parameters":[{"name":"group_address","in":"path","required":true,"schema":{"type":"string","description":"42-char 0x-prefixed group address (short group id also accepted for back-compat)","title":"Group Address"},"description":"42-char 0x-prefixed group address (short group id also accepted for back-compat)"},{"name":"address","in":"path","required":true,"schema":{"type":"string","title":"Address"}},{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":1,"description":"Lookback window (capped at the group's flow_lookback_days).","default":180,"title":"Days"},"description":"Lookback window (capped at the group's flow_lookback_days)."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AvatarFlowsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/rep_score/groups/{group_address}/avatars/{address}/neighbours":{"get":{"tags":["Rep Score"],"summary":"Avatar Neighbours","description":"Trust-graph 1-hop view for a single avatar.\n\nReturns the focal's score plus every other avatar that has at least one\ntrust edge with the focal, joined against `rep_score_state` so each\nneighbour carries its own score and components when we have one.","operationId":"avatar_neighbours_rep_score_groups__group_address__avatars__address__neighbours_get","parameters":[{"name":"group_address","in":"path","required":true,"schema":{"type":"string","description":"42-char 0x-prefixed group address (short group id also accepted for back-compat)","title":"Group Address"},"description":"42-char 0x-prefixed group address (short group id also accepted for back-compat)"},{"name":"address","in":"path","required":true,"schema":{"type":"string","title":"Address"}},{"name":"max_neighbours","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"description":"Cap on returned neighbours (sorted by reputation_score DESC, with scored neighbours first).","default":100,"title":"Max Neighbours"},"description":"Cap on returned neighbours (sorted by reputation_score DESC, with scored neighbours first)."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AvatarNeighboursResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/rep_score/groups/{group_address}/avatars/{address}/history":{"get":{"tags":["Rep Score"],"summary":"Avatar History","operationId":"avatar_history_rep_score_groups__group_address__avatars__address__history_get","parameters":[{"name":"group_address","in":"path","required":true,"schema":{"type":"string","description":"42-char 0x-prefixed group address (short group id also accepted for back-compat)","title":"Group Address"},"description":"42-char 0x-prefixed group address (short group id also accepted for back-compat)"},{"name":"address","in":"path","required":true,"schema":{"type":"string","title":"Address"}},{"name":"since","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Since"}},{"name":"until","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Until"}},{"name":"reason","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated subset of: first_sight, score_delta, behaviour_delta, membership_flip, algorithm_change.","title":"Reason"},"description":"Comma-separated subset of: first_sight, score_delta, behaviour_delta, membership_flip, algorithm_change."},{"name":"limit","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":10000,"minimum":1},{"type":"null"}],"default":200,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"details","in":"query","required":false,"schema":{"type":"boolean","description":"If false, omit per-row detail blocks (components, ema_primitives, instantaneous). reputation_score and reputation_score_live are still returned on every row.","default":true,"title":"Details"},"description":"If false, omit per-row detail blocks (components, ema_primitives, instantaneous). reputation_score and reputation_score_live are still returned on every row."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AvatarHistoryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/rep_score/groups/{group_address}/changes-history":{"get":{"tags":["Rep Score"],"summary":"Changes History","description":"Group-wide history-of-changes feed within a time window.\n\nPowers the Activity tab's historical sub-panel: a time-series of\nevery material score change in the window, optionally filtered by\n`change_reason`. Newest first (deterministic `avatar` tiebreaker),\ncapped at `limit=5000` per call; `truncated=true` on the response\nmeans more rows exist in the window — fetch the next page with\n`offset += limit`.","operationId":"changes_history_rep_score_groups__group_address__changes_history_get","parameters":[{"name":"group_address","in":"path","required":true,"schema":{"type":"string","description":"42-char group address or short id","title":"Group Address"},"description":"42-char group address or short id"},{"name":"since","in":"query","required":true,"schema":{"type":"string","format":"date-time","description":"UTC start of the window (inclusive).","title":"Since"},"description":"UTC start of the window (inclusive)."},{"name":"until","in":"query","required":true,"schema":{"type":"string","format":"date-time","description":"UTC end of the window (inclusive).","title":"Until"},"description":"UTC end of the window (inclusive)."},{"name":"reason","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by change_reason. Repeatable: ?reason=score_delta&reason=membership_flip","title":"Reason"},"description":"Filter by change_reason. Repeatable: ?reason=score_delta&reason=membership_flip"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":5000,"minimum":1,"default":5000,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Pagination cursor: skip this many rows of the (snapshot_at DESC, avatar ASC)-ordered window. Combine with `truncated` on the response to walk past the per-call row cap.","default":0,"title":"Offset"},"description":"Pagination cursor: skip this many rows of the (snapshot_at DESC, avatar ASC)-ordered window. Combine with `truncated` on the response to walk past the per-call row cap."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeHistoryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/rep_score/groups/{group_address}/changes":{"get":{"tags":["Rep Score"],"summary":"Group Changes","description":"Delta feed for score-groups-backend.\n\nReturns the (address, score_uint) pairs whose live effective score\n(rounded to a uint integer at the configured ``score_scale``) has\nchanged since ``since_seq`` for the given group. ``score_uint = 0``\nis emitted for non-members and for any avatar whose effective score\nrounds to zero — both map to score-groups-backend's \"leaf deletion\"\nsemantics.\n\nEach call re-evaluates the live layer (cached score × current B/O\nliveness) for every member in one postgres batch, diffs against\n``rep_score_emitted_state``, allocates a new per-group seq for each\nactual change, then returns rows with ``seq > since_seq`` ordered by\nseq ASC.","operationId":"group_changes_rep_score_groups__group_address__changes_get","parameters":[{"name":"group_address","in":"path","required":true,"schema":{"type":"string","description":"42-char 0x-prefixed group address (short group id also accepted for back-compat)","title":"Group Address"},"description":"42-char 0x-prefixed group address (short group id also accepted for back-compat)"},{"name":"since_seq","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Return rows with seq > since_seq. Pass 0 to bootstrap.","default":0,"title":"Since Seq"},"description":"Return rows with seq > since_seq. Pass 0 to bootstrap."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":1000,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeFeedResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/rep_score/groups/{group_address}/history-compare":{"get":{"tags":["Rep Score"],"summary":"History Compare","description":"Per-avatar score diff between two group variants at a shared backfill tick.\n\nUseful after running ``backfill`` on two variant group IDs to compare\nhow different SQL dialects or algorithm params affect scores. Returns\nonly avatars present in BOTH variants at the given timestamp, ordered\nby |delta| DESC so the biggest movers surface first.","operationId":"history_compare_rep_score_groups__group_address__history_compare_get","parameters":[{"name":"group_address","in":"path","required":true,"schema":{"type":"string","description":"42-char group address (used only for context; both variants must share it)","title":"Group Address"},"description":"42-char group address (used only for context; both variants must share it)"},{"name":"id_a","in":"query","required":true,"schema":{"type":"string","description":"group_id of variant A","title":"Id A"},"description":"group_id of variant A"},{"name":"id_b","in":"query","required":true,"schema":{"type":"string","description":"group_id of variant B","title":"Id B"},"description":"group_id of variant B"},{"name":"at","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Snapshot timestamp to compare at. Defaults to the latest tick present in both variants.","title":"At"},"description":"Snapshot timestamp to compare at. Defaults to the latest tick present in both variants."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HistoryCompareResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/rep_score/dev/refresh":{"post":{"tags":["Rep Score"],"summary":"Manual Refresh","operationId":"manual_refresh_rep_score_dev_refresh_post","parameters":[{"name":"group_address","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Group address (or short id for back-compat). Omit to refresh every group.","title":"Group Address"},"description":"Group address (or short id for back-compat). Omit to refresh every group."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshTriggerResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/analytics/risk-score":{"get":{"tags":["Analytics"],"summary":"List Risk Scores","description":"Latest risk score for every avatar, ordered by score DESC.\n\nScores are computed by the CatBoost transaction-guard model (``model_id``\nidentifies the exact checkpoint). Recomputed by the daily\n``compute_danger_scores`` batch job.","operationId":"list_risk_scores_analytics_risk_score_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":10000,"minimum":1,"default":1000,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"min_score","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Lower bound (inclusive) on score 0–100","title":"Min Score"},"description":"Lower bound (inclusive) on score 0–100"},{"name":"max_score","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Upper bound (inclusive) on score 0–100","title":"Max Score"},"description":"Upper bound (inclusive) on score 0–100"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DangerScoresResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/analytics/risk-score/{address}":{"get":{"tags":["Analytics"],"summary":"Get Risk Score","description":"Latest risk score for one avatar. 404 when not yet scored.","operationId":"get_risk_score_analytics_risk_score__address__get","parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string","description":"42-char 0x-prefixed avatar address","title":"Address"},"description":"42-char 0x-prefixed avatar address"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DangerScoreEntry"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/group-bot-detection/flagged":{"get":{"tags":["GroupBotDetection"],"summary":"List Flagged","description":"Paginated list of flagged members with evidence (from the snapshot).","operationId":"list_flagged_group_bot_detection_flagged_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":5000,"minimum":1},{"type":"null"}],"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"group","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by configured group id","title":"Group"},"description":"Filter by configured group id"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlaggedResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/group-bot-detection/stats":{"get":{"tags":["GroupBotDetection"],"summary":"Stats","description":"Summary: total flagged, breakdown by signal set, and top name clusters.","operationId":"stats_group_bot_detection_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatsResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/group-bot-detection/health":{"get":{"tags":["GroupBotDetection"],"summary":"Health","description":"Liveness + snapshot freshness.","operationId":"health_group_bot_detection_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/health/live":{"get":{"summary":"Health Live","description":"Liveness — 200 unconditionally if the process is alive.","operationId":"health_live_health_live_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/health/ready":{"get":{"summary":"Health Ready","description":"Readiness — 200 only when AA's dependencies are reachable.","operationId":"health_ready_health_ready_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}}},"components":{"schemas":{"AddressVerdict":{"properties":{"address":{"type":"string","title":"Address","description":"Ethereum address"},"is_bot":{"type":"boolean","title":"Is Bot","description":"Whether the address is classified as a bot"},"category":{"anyOf":[{"$ref":"#/components/schemas/ClassificationCategory"},{"type":"null"}],"description":"Classification category"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason","description":"Reason for classification"}},"type":"object","required":["address","is_bot"],"title":"AddressVerdict","description":"Individual address classification result - keeping original structure"},"AvatarFlowRow":{"properties":{"date":{"type":"string","title":"Date"},"balance":{"type":"number","title":"Balance","default":0.0},"outstanding":{"type":"number","title":"Outstanding","default":0.0},"transfer_in":{"type":"number","title":"Transfer In","default":0.0},"transfer_out":{"type":"number","title":"Transfer Out","default":0.0},"mint":{"type":"number","title":"Mint","default":0.0},"qualified_inflow":{"type":"number","title":"Qualified Inflow","default":0.0},"qualified_outflow":{"type":"number","title":"Qualified Outflow","default":0.0},"out_offers":{"type":"number","title":"Out Offers","default":0.0},"out_gateway":{"type":"number","title":"Out Gateway","default":0.0},"out_merchant":{"type":"number","title":"Out Merchant","default":0.0},"out_topup":{"type":"number","title":"Out Topup","default":0.0},"in_cashback":{"type":"number","title":"In Cashback","default":0.0},"in_inviter_fee":{"type":"number","title":"In Inviter Fee","default":0.0}},"type":"object","required":["date"],"title":"AvatarFlowRow"},"AvatarFlowsResponse":{"properties":{"group_id":{"type":"string","title":"Group Id"},"group_address":{"type":"string","title":"Group Address"},"address":{"type":"string","title":"Address"},"daily_flows_variant":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Daily Flows Variant"},"days":{"type":"integer","title":"Days"},"items":{"items":{"$ref":"#/components/schemas/AvatarFlowRow"},"type":"array","title":"Items"}},"type":"object","required":["group_id","group_address","address","days","items"],"title":"AvatarFlowsResponse"},"AvatarHistoryEntry":{"properties":{"snapshot_at":{"type":"string","format":"date-time","title":"Snapshot At"},"raw_score":{"type":"number","title":"Raw Score"},"reputation_score":{"type":"integer","title":"Reputation Score","description":"UNBOUNDED user-facing score, floored to int (snapshot at history time, L̃=1)."},"reputation_score_live":{"type":"integer","title":"Reputation Score Live","description":"History rows are precompute snapshots; we don't recompose historic data against current B/O. Equals `max(0, reputation_score)` (floored at 0 to keep the ≥0 live contract uniform)."},"behaviour_score":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Behaviour Score"},"boost_score":{"type":"number","title":"Boost Score","description":"Sum of attestation-driven boost components (B_static + B_network) in 0–100 point units. 0.0 when no boost has been computed yet.","default":0.0},"liveness_factor":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Liveness Factor","description":"L̃ at this history tick — the gate multiplier captured at refresh time (= gate_penalty if the debt walk tripped, else 1.0). Mirrors the `HistoryRow.liveness_factor` column so dashboard charts can plot the gate over time without re-reading the nested `components.gate.snapshot.liveness_factor`."},"is_member":{"type":"boolean","title":"Is Member"},"components":{"anyOf":[{"$ref":"#/components/schemas/Components"},{"type":"null"}]},"change_reason":{"type":"string","title":"Change Reason"},"prev_raw_score":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Prev Raw Score"},"prev_reputation_score":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Prev Reputation Score","description":"Previous score on the SAME unbounded scale as `reputation_score` (preceding history row's unclipped s_user_raw; falls back to prev_raw_score·100 only while that sits below its 1.0 clip ceiling). None when unknowable."},"prev_behaviour_score":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Prev Behaviour Score"},"prev_is_member":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Prev Is Member"},"run_id":{"type":"string","title":"Run Id"},"algorithm":{"type":"string","title":"Algorithm"},"algorithm_version":{"type":"string","title":"Algorithm Version"},"params_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Params Hash"},"snapshot_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Snapshot Hash"}},"type":"object","required":["snapshot_at","raw_score","reputation_score","reputation_score_live","behaviour_score","is_member","change_reason","run_id","algorithm","algorithm_version"],"title":"AvatarHistoryEntry"},"AvatarHistoryResponse":{"properties":{"group_id":{"type":"string","title":"Group Id"},"default":{"type":"boolean","title":"Default"},"address":{"type":"string","title":"Address"},"total":{"type":"integer","title":"Total"},"limit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Limit"},"offset":{"type":"integer","title":"Offset"},"items":{"items":{"$ref":"#/components/schemas/AvatarHistoryEntry"},"type":"array","title":"Items"}},"type":"object","required":["group_id","default","address","total","limit","offset","items"],"title":"AvatarHistoryResponse"},"AvatarNeighboursResponse":{"properties":{"group_id":{"type":"string","title":"Group Id"},"default":{"type":"boolean","title":"Default"},"address":{"type":"string","title":"Address"},"source":{"type":"string","enum":["cached","cold_start"],"title":"Source"},"is_member":{"type":"boolean","title":"Is Member"},"raw_score":{"type":"number","title":"Raw Score"},"reputation_score":{"type":"integer","title":"Reputation Score"},"behaviour_score":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Behaviour Score"},"raw_behaviour_score":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Raw Behaviour Score","description":"Unrounded focal s_B in 0-1 scale. Mirrors the neighbour-level field for use in contribution-share math."},"propagation_alpha":{"type":"number","title":"Propagation Alpha","description":"α anchor weight from the propagation params; useful for the dashboard to compute per-neighbour contribution shares."},"propagation_delta":{"type":"number","title":"Propagation Delta"},"propagation_mu_delta":{"type":"number","title":"Propagation Mu Delta","description":"μ_delta — the B_delta momentum gain. The dashboard uses it to decompose this refresh's daily_change as μ·Σ M[focal,j]·Δs_eff[j].","default":0.0},"total_neighbours":{"type":"integer","title":"Total Neighbours"},"neighbours":{"items":{"$ref":"#/components/schemas/NeighbourEntry"},"type":"array","title":"Neighbours"}},"type":"object","required":["group_id","default","address","source","is_member","raw_score","reputation_score","behaviour_score","propagation_alpha","propagation_delta","total_neighbours","neighbours"],"title":"AvatarNeighboursResponse"},"AvatarStateResponse":{"properties":{"group_id":{"type":"string","title":"Group Id"},"group_address":{"type":"string","title":"Group Address"},"default":{"type":"boolean","title":"Default"},"address":{"type":"string","title":"Address"},"source":{"type":"string","enum":["cached","cold_start"],"title":"Source"},"is_member":{"type":"boolean","title":"Is Member"},"non_member_scoring":{"anyOf":[{"type":"string","enum":["trust_only","economic"]},{"type":"null"}],"title":"Non Member Scoring"},"raw_score":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Raw Score","description":"0–1 internal scale (clipped) — the rep_v1 surface. Omitted for rep_v2 (redundant with reputation_score / reputation_score_live)."},"reputation_score":{"type":"integer","title":"Reputation Score","description":"UNBOUNDED user-facing score, floored to int. SNAPSHOT view: the `s_user_raw` at the last precompute (L̃=1, before live recompose). Can be negative or > 100."},"reputation_score_live":{"type":"integer","title":"Reputation Score Live","description":"≥0, NOT upper-bounded, rounded to int: `max(0, round(s_user_gated))`. LIVE view: `s_user_gated` (= s_user_raw · L̃) recomposed at request time with the live transient L̃ from the current B/O reading — the debt-walk gate is folded into the headline score (collapses toward 0 when the gate fires). Falls back to `max(0, reputation_score)` when live data isn't available (`live=false`, cold-start; L̃=1 there, so gated == raw)."},"behaviour_score":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Behaviour Score","description":"Pre-propagation s_B, 0–100 scale"},"boost_score":{"type":"number","title":"Boost Score","description":"Sum of attestation-driven boost components (B_static + B_network) in 0–100 point units. 0.0 when no boost has been computed yet.","default":0.0},"blacklisted":{"type":"boolean","title":"Blacklisted","description":"True when the avatar is on the blacklist. The headline scores (reputation_score, reputation_score_live, behaviour_score, boost_score) are then forced to 0 regardless of computed value.","default":false},"components":{"anyOf":[{"$ref":"#/components/schemas/Components"},{"type":"null"}]},"algorithm":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Algorithm"},"algorithm_version":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Algorithm Version"},"params_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Params Hash"},"snapshot_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Snapshot Hash"},"computed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Computed At"},"danger_score":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Danger Score","description":"Latest CatBoost danger score (0–100). None when the danger-score batch has not yet run for this avatar."}},"type":"object","required":["group_id","group_address","default","address","source","is_member","reputation_score","reputation_score_live"],"title":"AvatarStateResponse"},"BehaviourStage":{"properties":{"R_bar":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"R Bar"},"Q_bar":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Q Bar"},"I_bar":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"I Bar"},"s_b":{"type":"number","title":"S B"},"ema_primitives":{"anyOf":[{"$ref":"#/components/schemas/EmaPrimitives"},{"type":"null"}]}},"type":"object","required":["s_b"],"title":"BehaviourStage","description":"Stage 1 — behaviour layer.\n\nThe named ratio outputs (R̄/Q̄/Ī/s_b) at the top, with the persistent\nEMA state nested for forensics."},"BoostStage":{"properties":{"B_static":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"B Static"},"B_static_live":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"B Static Live"},"b_static_sources":{"anyOf":[{"additionalProperties":{"type":"number"},"type":"object"},{"type":"null"}],"title":"B Static Sources"},"b_static_sources_live":{"anyOf":[{"additionalProperties":{"type":"number"},"type":"object"},{"type":"null"}],"title":"B Static Sources Live"},"B_network":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"B Network"},"B_delta":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"B Delta"},"B_legacy":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"B Legacy"},"B_legacy_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"B Legacy Active"},"B_total":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"B Total"},"delta_state":{"anyOf":[{"$ref":"#/components/schemas/DeltaState"},{"type":"null"}]}},"type":"object","title":"BoostStage","description":"Stage 3 — boost stack.\n\nFour boost layers (`B_static`, `B_network`, `B_delta`, `B_legacy`)\nand their sum `B_total`. `B_static` is the refresh-time frozen\nvalue (velocity input for the next refresh); `B_static_live` is\nupdated by the 10-s fast path (`api._ensure_b_static_fresh`)\nbetween refreshes — UI consumers should prefer `_live`. Group-wide\nmode knobs (`mode`, `mu`, `gamma`, `lambda_static`, `pos_matrix`,\n`neg_matrix`, `tau_days`) live in `/config.boost.delta`; the\nB_static attestation sources live in `/config.boost.static.sources`\nand the bilateral-network knobs in `/config.boost.network`.\n\n`B_legacy` is the decaying credit from the legacy\nrelative-trustscore snapshot — purely additive into B_total and\nintentionally invisible to the momentum integrator's velocity.\nSee `/config.boost.legacy` (snapshot_path, migration_start_at,\ntau_L_days, scale)."},"BotAnalyticsRequest":{"properties":{"address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address","description":"Single address to analyze"},"addresses":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Addresses","description":"Batch of addresses"},"use_classifier":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Use Classifier","description":"Override use of ML classifier"}},"type":"object","title":"BotAnalyticsRequest","description":"Request model for bot analytics classification"},"BotAnalyticsResponse":{"properties":{"status":{"type":"string","title":"Status","description":"Response status"},"verdicts":{"items":{"$ref":"#/components/schemas/AddressVerdict"},"type":"array","title":"Verdicts","description":"Classification results"},"total_processed":{"type":"integer","title":"Total Processed","description":"Total addresses processed"},"processing_time_ms":{"type":"number","title":"Processing Time Ms","description":"Processing time in milliseconds"},"classifier_used":{"type":"boolean","title":"Classifier Used","description":"Whether ML classifier was used"}},"type":"object","required":["status","verdicts","total_processed","processing_time_ms","classifier_used"],"title":"BotAnalyticsResponse","description":"Response model for bot analytics classification"},"ChangeFeedItem":{"properties":{"address":{"type":"string","title":"Address"},"score_uint":{"type":"string","title":"Score Uint"},"is_member":{"type":"boolean","title":"Is Member"},"seq":{"type":"integer","title":"Seq"},"emitted_at":{"type":"string","format":"date-time","title":"Emitted At"}},"type":"object","required":["address","score_uint","is_member","seq","emitted_at"],"title":"ChangeFeedItem","description":"One avatar whose live effective score moved since the consumer's\nlast cursor.\n\n`score_uint` is the stringified `reputation_score_live`\n(`max(0, round(s_user_gated))`): ≥0 (0 = leaf deletion) but NOT\nupper-bounded — it may exceed 100. Returned as a decimal string (we\nmirror score-groups-backend's stringified uint convention so the\nconsumer can copy the value into its uint256 leaf without parsing\nsurprises). `seq` is the per-group monotonic that the consumer feeds\nback as `since_seq` on the next poll."},"ChangeFeedResponse":{"properties":{"group_id":{"type":"string","title":"Group Id"},"group_address":{"type":"string","title":"Group Address"},"default":{"type":"boolean","title":"Default"},"algorithm":{"type":"string","title":"Algorithm"},"algorithm_version":{"type":"string","title":"Algorithm Version"},"score_scale":{"type":"integer","title":"Score Scale"},"items":{"items":{"$ref":"#/components/schemas/ChangeFeedItem"},"type":"array","title":"Items"},"next_seq":{"type":"integer","title":"Next Seq"},"has_more":{"type":"boolean","title":"Has More"},"recomputed_at":{"type":"string","format":"date-time","title":"Recomputed At"}},"type":"object","required":["group_id","group_address","default","algorithm","algorithm_version","score_scale","items","next_seq","has_more","recomputed_at"],"title":"ChangeFeedResponse","description":"Paginated delta feed; items contain only avatars whose `score_uint`\nactually changed since `since_seq`."},"ChangeHistoryItem":{"properties":{"avatar":{"type":"string","title":"Avatar"},"snapshot_at":{"type":"string","format":"date-time","title":"Snapshot At"},"reputation_score":{"type":"integer","title":"Reputation Score","description":"UNBOUNDED user-facing score, floored to int (history snapshot)."},"prev_reputation_score":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Prev Reputation Score","description":"Previous score on the SAME unbounded scale as `reputation_score` (the preceding history row's unclipped s_user_raw). None when no predecessor is known — including the case where only the stored 0–1 prev exists and sits at its 1.0 clip ceiling, where the true previous raw is unknowable."},"delta":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Delta","description":"reputation_score − prev_reputation_score, both on the unbounded scale. None whenever prev_reputation_score is None."},"behaviour_score":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Behaviour Score"},"change_reason":{"type":"string","title":"Change Reason"},"run_id":{"type":"string","title":"Run Id"}},"type":"object","required":["avatar","snapshot_at","reputation_score","change_reason","run_id"],"title":"ChangeHistoryItem","description":"One row of the group-wide change feed, scoped to a time window.\n\nLighter than :class:`AvatarHistoryEntry` — no nested `components`,\njust the headline fields the Activity timeline / top-movers view\nneeds. `delta = reputation_score − prev_reputation_score` is\npre-computed server-side when both endpoints are populated."},"ChangeHistoryResponse":{"properties":{"group_id":{"type":"string","title":"Group Id"},"group_address":{"type":"string","title":"Group Address"},"default":{"type":"boolean","title":"Default"},"since":{"type":"string","format":"date-time","title":"Since"},"until":{"type":"string","format":"date-time","title":"Until"},"total":{"type":"integer","title":"Total","description":"Rows in THIS page (back-compat: not the window total). Use `truncated` to detect more rows in the window."},"offset":{"type":"integer","title":"Offset","default":0},"truncated":{"type":"boolean","title":"Truncated","description":"True when the window holds more rows past this page — fetch the next page with `offset += limit`. Ordering is deterministic (snapshot_at DESC, avatar ASC), so pages don't skip or duplicate rows.","default":false},"items":{"items":{"$ref":"#/components/schemas/ChangeHistoryItem"},"type":"array","title":"Items"}},"type":"object","required":["group_id","group_address","default","since","until","total","items"],"title":"ChangeHistoryResponse"},"ClassificationCategory":{"type":"string","enum":["blocked","flagged","allowed"],"title":"ClassificationCategory","description":"Classification categories - keeping original names"},"Components":{"properties":{"behaviour":{"$ref":"#/components/schemas/BehaviourStage"},"propagation":{"anyOf":[{"$ref":"#/components/schemas/PropagationStage"},{"type":"null"}]},"boost":{"anyOf":[{"$ref":"#/components/schemas/BoostStage"},{"type":"null"}]},"composition":{"anyOf":[{"$ref":"#/components/schemas/CompositionStage"},{"type":"null"}]},"gate":{"anyOf":[{"$ref":"#/components/schemas/GateStage"},{"type":"null"}]}},"type":"object","required":["behaviour"],"title":"Components","description":"The full score-pipeline decomposition for one avatar.\n\nWalk the JSON top-to-bottom to follow the score computation:\nbehaviour → propagation → boost → composition → gate.\n\nEach stage carries only per-avatar outputs and internal state —\ngroup-wide config (algorithm switches, numerical knobs) lives in\n`/config`. Stages downstream of behaviour are `None` for cold-start\nrows that never propagated."},"CompositionStage":{"properties":{"s_eff_used":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"S Eff Used"},"base":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Base"},"s_user_raw":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"S User Raw"}},"type":"object","title":"CompositionStage","description":"Stage 4 — composition (gate-free).\n\nBuilds `s_user_raw` from `s_eff_used + B_total`. The gate is applied\nin Stage 5 (see `GateStageSnapshot` / `GateStageLive`). `mode` and\n`delta_placement` knobs live in `/config`."},"ConfigResponse":{"properties":{"enabled":{"type":"boolean","title":"Enabled"},"refresh_interval_seconds":{"type":"integer","title":"Refresh Interval Seconds"},"defaults":{"type":"object","title":"Defaults"},"groups":{"items":{"type":"object"},"type":"array","title":"Groups"}},"type":"object","required":["enabled","refresh_interval_seconds","defaults","groups"],"title":"ConfigResponse"},"DangerScoreEntry":{"properties":{"avatar":{"type":"string","title":"Avatar"},"danger_score":{"type":"number","title":"Danger Score","description":"0–100 normalised risk score"},"danger_score_raw":{"type":"number","title":"Danger Score Raw","description":"0–1 raw model output"},"model_id":{"type":"string","title":"Model Id"},"computed_at":{"type":"string","format":"date-time","title":"Computed At"}},"type":"object","required":["avatar","danger_score","danger_score_raw","model_id","computed_at"],"title":"DangerScoreEntry"},"DangerScoresResponse":{"properties":{"total":{"type":"integer","title":"Total"},"limit":{"type":"integer","title":"Limit"},"offset":{"type":"integer","title":"Offset"},"items":{"items":{"$ref":"#/components/schemas/DangerScoreEntry"},"type":"array","title":"Items"}},"type":"object","required":["total","limit","offset","items"],"title":"DangerScoresResponse"},"DeltaState":{"properties":{"b_mem":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"B Mem"},"b_mem_prev":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"B Mem Prev"},"daily_change":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Daily Change"},"dt_days":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Dt Days"},"s_eff_prev":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"S Eff Prev"}},"type":"object","title":"DeltaState","description":"Memory-mode B_delta integrator state for one avatar.\n\nPopulated only when the group's `boost.delta.mode == \"memory\"` (see\n`/config`); absent on windowed / off rows."},"EmaPrimitives":{"properties":{"r_bar":{"type":"number","title":"R Bar"},"qual_out_bar":{"type":"number","title":"Qual Out Bar","default":0.0},"tot_out_bar":{"type":"number","title":"Tot Out Bar","default":0.0},"qual_in_bar":{"type":"number","title":"Qual In Bar","default":0.0},"tot_in_bar":{"type":"number","title":"Tot In Bar","default":0.0},"mint_bar":{"type":"number","title":"Mint Bar","default":0.0}},"type":"object","required":["r_bar"],"title":"EmaPrimitives","description":"Raw EMA primitives — the algorithm's persistent state.\n\nSix-EMA mint-floor form (FORMULAS.md §3):\n  r_bar         — EMA of B / max(η, O)\n  qual_out_bar  — EMA of qualified outflow (CrcV2_TokenOffers_OfferClaimed.spent)\n  tot_out_bar   — EMA of total transfer_out\n  qual_in_bar   — EMA of qualified inflow (transfers from the cashback distributor)\n  tot_in_bar    — EMA of total transfer_in (mint excluded)\n  mint_bar      — EMA of mint volume"},"EndorserWeight":{"properties":{"address":{"type":"string","title":"Address"},"weight_row":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Weight Row"},"weight_budget":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Weight Budget"},"d_s_eff":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"D S Eff"},"d_static":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"D Static"},"contribution_positive":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Contribution Positive"},"contribution_negative":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Contribution Negative"},"contribution":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Contribution"}},"type":"object","required":["address"],"title":"EndorserWeight","description":"One nonzero entry of an avatar's row in the endorsement matrices.\n\n`weight_row` is M[focal, address] — the share of `address`'s score\nmove under the row-stochastic, s_B-weighted endorsement matrix.\n`weight_budget` is M_budget[focal, address] = `address`'s s_B / its\nout-degree, surfaced when at least one momentum band uses the budget\nmatrix.\n\n`d_s_eff` / `d_static` are this-refresh deltas on the endorser:\nΔs_eff and ΔB_static. `contribution_positive` and\n`contribution_negative` are the bands' shares of `daily_change`:\n\n    contribution_positive = μ · weight_band_pos · max(0, v[endorser])\n    contribution_negative = μ · weight_band_neg · min(0, v[endorser])\n\nwhere `v[endorser] = Δs_eff[endorser] + λ_static · Δ_B_static[endorser] / 100`.\n`contribution` is `contribution_positive + contribution_negative`.\nPersisted per refresh so each history row is self-decomposable and\nthe standing B_delta stays attributable."},"ErrorResponse":{"properties":{"status":{"type":"string","title":"Status","default":"error"},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message","description":"Optional message"},"timestamp":{"type":"string","format":"date-time","title":"Timestamp"},"error_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Code","description":"Error code"},"details":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Details","description":"Error details"}},"type":"object","title":"ErrorResponse","description":"Error response model"},"FlaggedMember":{"properties":{"address":{"type":"string","title":"Address"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"signals":{"items":{"type":"string"},"type":"array","title":"Signals","description":"Flagging signals that fired"},"stem":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stem","description":"Enumerated-name cluster stem"},"cluster_size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Cluster Size"},"origin_inviter":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Origin Inviter"},"batch_tx":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Batch Tx"},"inviter_member_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Inviter Member Count"},"batch_size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Batch Size"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason","description":"Blacklist reason applied when written"}},"type":"object","required":["address"],"title":"FlaggedMember","description":"A flagged group member plus the evidence behind the flag."},"FlaggedResponse":{"properties":{"status":{"type":"string","title":"Status","default":"success"},"group":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Group"},"total":{"type":"integer","title":"Total","default":0},"limit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Limit"},"offset":{"type":"integer","title":"Offset","default":0},"computed_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Computed At"},"items":{"items":{"$ref":"#/components/schemas/FlaggedMember"},"type":"array","title":"Items"}},"type":"object","title":"FlaggedResponse"},"FlowsBlock":{"properties":{"transfer_in":{"type":"number","title":"Transfer In","default":0.0},"transfer_out":{"type":"number","title":"Transfer Out","default":0.0},"mint":{"type":"number","title":"Mint","default":0.0},"qualified_inflow":{"type":"number","title":"Qualified Inflow","default":0.0},"qualified_outflow":{"type":"number","title":"Qualified Outflow","default":0.0},"net_flow":{"type":"number","title":"Net Flow","default":0.0}},"type":"object","title":"FlowsBlock","description":"Five flow primitives + derived `net_flow` for one aggregation\nwindow (window / last_day / last_24h / last_7d)."},"GateStage":{"properties":{"snapshot":{"anyOf":[{"$ref":"#/components/schemas/GateStageSnapshot"},{"type":"null"}]},"live":{"anyOf":[{"$ref":"#/components/schemas/GateStageLive"},{"type":"null"}]}},"type":"object","title":"GateStage","description":"Stage 5 container — snapshot + live views of the gate."},"GateStageLive":{"properties":{"balance":{"type":"number","title":"Balance"},"outstanding":{"type":"number","title":"Outstanding"},"non_qualified_outflow_window":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Non Qualified Outflow Window"},"qualified_inflow_window":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Qualified Inflow Window"},"gate_debt":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Gate Debt"},"gate_triggered":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Gate Triggered"},"liveness_factor":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Liveness Factor"},"s_user_raw":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"S User Raw"},"s_user_gated":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"S User Gated"},"s_user":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"S User"},"clipped":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Clipped"},"score_uint":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Score Uint"}},"type":"object","required":["balance","outstanding"],"title":"GateStageLive","description":"Stage 5 — gate (recomputed at request time).\n\nSame shape as `GateStageSnapshot` but with live B/O and live window\nflows. `liveness_factor` is L̃ in FORMULAS.md. Differs from\nsnapshot when the live gate triggers or `B_static_live` has drifted\nahead of `B_static`."},"GateStageSnapshot":{"properties":{"as_of":{"type":"string","format":"date-time","title":"As Of"},"balance":{"type":"number","title":"Balance"},"outstanding":{"type":"number","title":"Outstanding"},"non_qualified_outflow_window":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Non Qualified Outflow Window"},"qualified_inflow_window":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Qualified Inflow Window"},"gate_debt":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Gate Debt"},"gate_triggered":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Gate Triggered"},"liveness_factor":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Liveness Factor"},"s_user_raw":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"S User Raw"},"s_user_gated":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"S User Gated"},"s_user":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"S User"},"clipped":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Clipped"},"score_uint":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Score Uint"}},"type":"object","required":["as_of","balance","outstanding"],"title":"GateStageSnapshot","description":"Stage 5 — gate (snapshot at refresh time).\n\nLive-layer state at refresh time: B/O snapshot, gate inputs (the\ndebt walk over the rolling window), the **liveness factor L̃**, and\nthe composition output AFTER applying the gate. At refresh time\nL̃ ≡ 1 (the gate is recomputed at request time), so these values\ntypically match `composition.s_user_raw` modulo `B_static_live`\ndrift.\n\n`liveness_factor` is L̃ in FORMULAS.md — the final-stage multiplier\napplied to `s_user_raw`. It equals `gate_penalty` when the debt\nwalk trips the threshold and 1.0 otherwise. (Pre-rename this field\nwas confusingly named `gate` — same name as the parent block.)\n\nCliff config (`window_hours`, `threshold_gcrc`, `penalty`) lives\nin `/config`."},"GroupScoreEntry":{"properties":{"address":{"type":"string","title":"Address"},"is_member":{"type":"boolean","title":"Is Member"},"reputation_score":{"type":"integer","title":"Reputation Score","description":"UNBOUNDED user-facing score, floored to int (snapshot at last precompute, L̃=1)."},"reputation_score_live":{"type":"integer","title":"Reputation Score Live","description":"≥0, NOT upper-bounded, rounded to int: `max(0, round(s_user_gated))`. `s_user_gated` (= s_user_raw · L̃) recomposed with live L̃ — the debt-walk gate is folded into the score. Equals `max(0, reputation_score)` when live data isn't available (L̃=1 there, so gated == raw). The stringified form is `score_uint`."},"behaviour_score":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Behaviour Score"},"boost_score":{"type":"number","title":"Boost Score","description":"Sum of attestation-driven boost components (B_static + B_network) in 0–100 point units. 0.0 when no boost has been computed yet.","default":0.0},"momentum_score":{"type":"number","title":"Momentum Score","description":"Momentum contribution to the boost (γ·B_delta) in rep-point units — the leaky-integrator network push/drag on this avatar's score, signed. 0.0 when momentum is disabled or not yet computed.","default":0.0},"blacklisted":{"type":"boolean","title":"Blacklisted","description":"True when the avatar is on the blacklist; headline scores are then forced to 0.","default":false},"components":{"anyOf":[{"$ref":"#/components/schemas/Components"},{"type":"null"}]},"score_uint":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Score Uint","description":"Decimal-stringified `reputation_score_live` (`max(0, round(s_user_gated))`) — the exact value `/changes` emits for this avatar. Populated when `?live=true` (the default); with `?live=false` there is no liveness signal so this field is omitted/null rather than a silently-wrong value. Blacklisted and non-member avatars emit \"0\"."},"params_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Params Hash"},"snapshot_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Snapshot Hash"},"computed_at":{"type":"string","format":"date-time","title":"Computed At"}},"type":"object","required":["address","is_member","reputation_score","reputation_score_live","behaviour_score","computed_at"],"title":"GroupScoreEntry"},"GroupScoresResponse":{"properties":{"group_id":{"type":"string","title":"Group Id"},"group_address":{"type":"string","title":"Group Address"},"default":{"type":"boolean","title":"Default"},"algorithm":{"type":"string","title":"Algorithm"},"algorithm_version":{"type":"string","title":"Algorithm Version"},"score_scale":{"type":"integer","title":"Score Scale","description":"Group config knob (default 100). NOTE: no longer applied to `score_uint` — that is now `max(0, round(s_user_gated))` (= reputation_score_live), unscaled. Retained for back-compat / parity with /changes."},"total":{"type":"integer","title":"Total"},"limit":{"type":"integer","title":"Limit"},"offset":{"type":"integer","title":"Offset"},"items":{"items":{"$ref":"#/components/schemas/GroupScoreEntry"},"type":"array","title":"Items"}},"type":"object","required":["group_id","group_address","default","algorithm","algorithm_version","score_scale","total","limit","offset","items"],"title":"GroupScoresResponse"},"GroupSummary":{"properties":{"id":{"type":"string","title":"Id"},"group_address":{"type":"string","title":"Group Address"},"default":{"type":"boolean","title":"Default"},"algorithm":{"type":"string","title":"Algorithm"},"member_source":{"type":"string","title":"Member Source"},"dual_publish":{"type":"boolean","title":"Dual Publish"},"member_count":{"type":"integer","title":"Member Count"},"last_run_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Run Status"},"last_run_started_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Run Started At"},"last_run_finished_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Run Finished At"},"last_run_rows_scored":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Last Run Rows Scored"}},"type":"object","required":["id","group_address","default","algorithm","member_source","dual_publish","member_count","last_run_status","last_run_started_at","last_run_finished_at","last_run_rows_scored"],"title":"GroupSummary"},"GroupsResponse":{"properties":{"enabled":{"type":"boolean","title":"Enabled"},"refresh_interval_seconds":{"type":"integer","title":"Refresh Interval Seconds"},"groups":{"items":{"$ref":"#/components/schemas/GroupSummary"},"type":"array","title":"Groups"}},"type":"object","required":["enabled","refresh_interval_seconds","groups"],"title":"GroupsResponse"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HealthResponse":{"properties":{"status":{"type":"string","enum":["ok","degraded","error"],"title":"Status"},"enabled":{"type":"boolean","title":"Enabled"},"refresh_interval_seconds":{"type":"integer","title":"Refresh Interval Seconds"},"last_refresh_age_seconds":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Last Refresh Age Seconds"},"last_run_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Run Status"},"postgres":{"type":"string","title":"Postgres"},"repository":{"type":"string","title":"Repository"},"groups":{"type":"integer","title":"Groups"}},"type":"object","required":["status","enabled","refresh_interval_seconds","last_refresh_age_seconds","last_run_status","postgres","repository","groups"],"title":"HealthResponse"},"HistoryCompareItem":{"properties":{"avatar":{"type":"string","title":"Avatar"},"score_a":{"type":"number","title":"Score A","description":"score (0–1 internal) for variant A"},"score_b":{"type":"number","title":"Score B","description":"score (0–1 internal) for variant B"},"reputation_score_a":{"type":"integer","title":"Reputation Score A","description":"score_a × 100, rounded"},"reputation_score_b":{"type":"integer","title":"Reputation Score B","description":"score_b × 100, rounded"},"delta":{"type":"integer","title":"Delta","description":"reputation_score_a − reputation_score_b"},"is_member_a":{"type":"boolean","title":"Is Member A"},"is_member_b":{"type":"boolean","title":"Is Member B"}},"type":"object","required":["avatar","score_a","score_b","reputation_score_a","reputation_score_b","delta","is_member_a","is_member_b"],"title":"HistoryCompareItem"},"HistoryCompareResponse":{"properties":{"group_address":{"type":"string","title":"Group Address"},"snapshot_at":{"type":"string","format":"date-time","title":"Snapshot At"},"group_id_a":{"type":"string","title":"Group Id A"},"algorithm_a":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Algorithm A"},"group_id_b":{"type":"string","title":"Group Id B"},"algorithm_b":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Algorithm B"},"count":{"type":"integer","title":"Count"},"items":{"items":{"$ref":"#/components/schemas/HistoryCompareItem"},"type":"array","title":"Items"}},"type":"object","required":["group_address","snapshot_at","group_id_a","algorithm_a","group_id_b","algorithm_b","count","items"],"title":"HistoryCompareResponse"},"HoldingsEntry":{"properties":{"address":{"type":"string","title":"Address"},"is_member":{"type":"boolean","title":"Is Member"},"balance":{"type":"number","title":"Balance"},"outstanding":{"type":"number","title":"Outstanding"},"bo_ratio":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Bo Ratio","description":"balance / max(η, outstanding); None when outstanding ≤ 0 AND balance is 0."},"flows":{"$ref":"#/components/schemas/HoldingsFlows"}},"type":"object","required":["address","is_member","balance","outstanding","flows"],"title":"HoldingsEntry","description":"One per-avatar holdings + flows row."},"HoldingsFlows":{"properties":{"window":{"$ref":"#/components/schemas/FlowsBlock"},"last_day":{"$ref":"#/components/schemas/FlowsBlock"},"last_24h":{"$ref":"#/components/schemas/FlowsBlock"},"last_7d":{"$ref":"#/components/schemas/FlowsBlock"}},"type":"object","required":["window","last_day","last_24h","last_7d"],"title":"HoldingsFlows","description":"Per-avatar flow aggregations at four windows.\n\n`window`   — sum over `flow_lookback_days` (180 default).\n`last_day` — the single most recent persisted daily row.\n`last_24h` — sum of the last 1 entry in `daily_flows_tail` (same\n             as `last_day` for current data; explicit for clarity).\n`last_7d`  — sum of the last 7 entries in `daily_flows_tail`."},"HoldingsResponse":{"properties":{"group_id":{"type":"string","title":"Group Id"},"group_address":{"type":"string","title":"Group Address"},"default":{"type":"boolean","title":"Default"},"total":{"type":"integer","title":"Total"},"limit":{"type":"integer","title":"Limit"},"sort_by":{"type":"string","title":"Sort By"},"order":{"type":"string","enum":["asc","desc"],"title":"Order"},"items":{"items":{"$ref":"#/components/schemas/HoldingsEntry"},"type":"array","title":"Items"}},"type":"object","required":["group_id","group_address","default","total","limit","sort_by","order","items"],"title":"HoldingsResponse"},"NeighbourEntry":{"properties":{"address":{"type":"string","title":"Address"},"edge_type":{"type":"string","enum":["bilateral","outgoing","incoming"],"title":"Edge Type"},"scored":{"type":"boolean","title":"Scored"},"is_member":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Member"},"raw_score":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Raw Score"},"reputation_score":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Reputation Score"},"behaviour_score":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Behaviour Score"},"raw_behaviour_score":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Raw Behaviour Score","description":"Unrounded s_B in 0-1 scale. Use this in contribution-share math; the rounded `behaviour_score` (0-100, 2 decimals) collapses tiny values to 0.00 and breaks share = s_B[j] / Σ s_B[k]."},"components":{"anyOf":[{"$ref":"#/components/schemas/Components"},{"type":"null"}]}},"type":"object","required":["address","edge_type","scored"],"title":"NeighbourEntry","description":"One trust-neighbour of the focal avatar.\n\n`edge_type` is one of:\n  - \"bilateral\": trust edges in both directions (the only kind that\n    contributes to propagation when delta = 0)\n  - \"outgoing\":  focal trusts neighbour, but neighbour does NOT\n    trust focal back\n  - \"incoming\":  neighbour trusts focal, focal does NOT trust back\n\n`scored = false` means we know the trust edge exists but the neighbour\ndoes not appear in `rep_score_state` for this group (i.e. they\naren't a member and the group isn't including non-members, or the\nrefresh hasn't picked them up yet). In that case the score fields\nare null."},"PropagationStage":{"properties":{"s_eff":{"type":"number","title":"S Eff"},"alpha_used":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Alpha Used"},"age_days":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Age Days"},"iters":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Iters"},"converged":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Converged"},"anchor_only":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Anchor Only"},"endorsers":{"anyOf":[{"items":{"$ref":"#/components/schemas/EndorserWeight"},"type":"array"},{"type":"null"}],"title":"Endorsers"}},"type":"object","required":["s_eff"],"title":"PropagationStage","description":"Stage 2 — trust propagation.\n\n`s_eff` is the post-propagation behaviour-score-in-graph output.\nThe rest is per-avatar provenance (which α the avatar got, how many\niterations to converge, the trust-graph row). Group-wide\n`aggregation` / α-curve config lives in `/config`."},"ProvenanceHistoryResponse":{"properties":{"group_id":{"type":"string","title":"Group Id"},"default":{"type":"boolean","title":"Default"},"items":{"items":{"$ref":"#/components/schemas/ProvenanceTransition"},"type":"array","title":"Items"}},"type":"object","required":["group_id","default","items"],"title":"ProvenanceHistoryResponse"},"ProvenanceTransition":{"properties":{"algorithm_version":{"type":"string","title":"Algorithm Version"},"params_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Params Hash"},"snapshot_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Snapshot Hash"},"first_seen":{"type":"string","format":"date-time","title":"First Seen"},"last_seen":{"type":"string","format":"date-time","title":"Last Seen"},"rows":{"type":"integer","title":"Rows"},"avatars":{"type":"integer","title":"Avatars"}},"type":"object","required":["algorithm_version","first_seen","last_seen","rows","avatars"],"title":"ProvenanceTransition","description":"One distinct (algorithm_version, params_hash, snapshot_hash)\nfingerprint observed in `rep_score_history` for this group.\n\n`first_seen` / `last_seen` bracket the window over which this\nfingerprint produced rows. `rows` is the total history-row count\nunder it; `avatars` is the distinct-avatar count. Pre-migration\nrows (no provenance) appear as a single record with both hashes\nset to `null`."},"RefreshTriggerResponse":{"properties":{"status":{"type":"string","enum":["ok","skipped","failed"],"title":"Status"},"group_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Group Id"},"rows_scored":{"type":"integer","title":"Rows Scored"},"elapsed_ms":{"type":"number","title":"Elapsed Ms"},"detail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Detail"}},"type":"object","required":["status","group_id","rows_scored","elapsed_ms"],"title":"RefreshTriggerResponse"},"RunScoresResponse":{"properties":{"group_id":{"type":"string","title":"Group Id"},"default":{"type":"boolean","title":"Default"},"run_id":{"type":"string","title":"Run Id"},"started_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Started At"},"count":{"type":"integer","title":"Count"},"scores":{"items":{"$ref":"#/components/schemas/ScoreDistEntry"},"type":"array","title":"Scores"}},"type":"object","required":["group_id","default","run_id","count","scores"],"title":"RunScoresResponse"},"RunSummary":{"properties":{"run_id":{"type":"string","title":"Run Id"},"status":{"type":"string","title":"Status"},"started_at":{"type":"string","format":"date-time","title":"Started At"},"finished_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Finished At"},"rows_scored":{"type":"integer","title":"Rows Scored"},"duration_seconds":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Duration Seconds","description":"(finished_at − started_at).total_seconds() when both are set; None for runs still in-flight."},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}},"type":"object","required":["run_id","status","started_at","rows_scored"],"title":"RunSummary","description":"One refresh run — used by the Runs tab and the\ndistribution-comparison picker."},"RunsResponse":{"properties":{"group_id":{"type":"string","title":"Group Id"},"default":{"type":"boolean","title":"Default"},"runs":{"items":{"$ref":"#/components/schemas/RunSummary"},"type":"array","title":"Runs"}},"type":"object","required":["group_id","default","runs"],"title":"RunsResponse"},"ScoreDistEntry":{"properties":{"address":{"type":"string","title":"Address"},"reputation_score":{"type":"integer","title":"Reputation Score"},"behaviour_score":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Behaviour Score"}},"type":"object","required":["address","reputation_score"],"title":"ScoreDistEntry","description":"One avatar's scores at a past run — the inputs the dashboard\nhistograms bin (`reputation_score` is the unclipped surface)."},"StatsResponse":{"properties":{"status":{"type":"string","title":"Status","default":"success"},"group":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Group"},"total_flagged":{"type":"integer","title":"Total Flagged","default":0},"by_signal":{"additionalProperties":{"type":"integer"},"type":"object","title":"By Signal"},"top_clusters":{"additionalProperties":{"type":"integer"},"type":"object","title":"Top Clusters"},"computed_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Computed At"}},"type":"object","title":"StatsResponse"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}}}