{"openapi":"3.1.0","info":{"title":"Affine API","description":"RESTful API for Affine validator infrastructure","version":"1.0.0"},"paths":{"/api/v1/rank/current":{"get":{"tags":["rank"],"summary":"Get Current Rank","description":"One public rank payload for the CLI/table view.\n\nThe split state readers remain implementation details; public callers get\none response containing only the status, queue head, and score table data\nrequired by ``af get-rank``.","operationId":"get_current_rank_api_v1_rank_current_get","parameters":[{"name":"top","in":"query","required":false,"schema":{"type":"integer","maximum":256,"minimum":1,"default":256,"title":"Top"}},{"name":"queue_limit","in":"query","required":false,"schema":{"type":"integer","maximum":256,"minimum":1,"default":256,"title":"Queue Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Current Rank Api V1 Rank Current Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/miners/uid/{uid}":{"get":{"tags":["Miners"],"summary":"Get Miner By Uid","operationId":"get_miner_by_uid_api_v1_miners_uid__uid__get","parameters":[{"name":"uid","in":"path","required":true,"schema":{"type":"integer","title":"Uid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MinerInfo"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/miners/hotkey/{hotkey}":{"get":{"tags":["Miners"],"summary":"Get Miner By Hotkey","operationId":"get_miner_by_hotkey_api_v1_miners_hotkey__hotkey__get","parameters":[{"name":"hotkey","in":"path","required":true,"schema":{"type":"string","title":"Hotkey"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MinerInfo"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/scores/latest":{"get":{"tags":["Scores"],"summary":"Get Latest Scores","description":"Latest scores for every currently-valid miner.\n\nSource-of-truth for the row list is :class:`MinersDAO`'s current\nvalid set, not the latest decided ``scores`` snapshot — so newly\nonline miners (and miners who registered after the last decide)\nappear immediately. Per-env averages come from sample_results\naggregation; the snapshot only contributes ``overall_score``\n(champion = 1.0, sort key) and the comparator-derived\n``scores_by_env`` for the last champion + previous champion.\n\nQuery parameters:\n- top: Number of top miners to return (default: 256, max: 256)","operationId":"get_latest_scores_api_v1_scores_latest_get","parameters":[{"name":"top","in":"query","required":false,"schema":{"type":"integer","maximum":256,"minimum":1,"description":"Return top N miners by score","default":32,"title":"Top"},"description":"Return top N miners by score"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScoresResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/scores/uid/{uid}":{"get":{"tags":["Scores"],"summary":"Get Score By Uid","description":"Get score for one miner by UID.\n\nReturns scores even when the miner doesn't appear in the latest\ndecided snapshot (e.g. they registered post-snapshot or have only\nbeen a non-winning challenger so far) — per-env averages come\nfrom ``sample_results`` aggregation in that case.","operationId":"get_score_by_uid_api_v1_scores_uid__uid__get","parameters":[{"name":"uid","in":"path","required":true,"schema":{"type":"integer","title":"Uid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MinerScore"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/scores/weights/latest":{"get":{"tags":["Scores"],"summary":"Get Latest Weights","description":"Return per-UID weights derived from recent score snapshots.\n\nPre-activation (``system_config`` row\n``weights_split_after_block`` missing or ``0``, or the latest\nsnapshot's ``block_number`` is below that threshold) this returns the\nscheduler's winner-takes-all snapshot. When the snapshot carries a\nwinner hotkey, the winner is resolved to that hotkey's current valid\nuid so recycled uids are not accidentally paid; if the hotkey is no\nlonger registered/valid, the winner share is returned on ``-1``,\nwhich the validator folds into UID 0 burn. Snapshots without a\nwinner hotkey keep the historical uid-only pass-through behavior.\n\nPost-activation we split weight evenly across the most recent\n``weights_split_champion_count`` (default 5) distinct champion\nhotkeys, resolved to their *current* on-chain uid via the miners\ntable. Each carries ``1/N`` weight. A hotkey that has since\nderegistered is skipped (we don't accidentally pay the successor on\nits recycled uid) and we keep walking history to backfill the count.\n\nBoth paths also include a ``config`` block derived from the latest\nsnapshot — flat rule constants (``win_margin``,\n``win_not_worse_tolerance``, ``win_min_dominant_envs``) plus\n``window_id`` (matching the pre-#449 path so legacy clients reading\n``config.win_min_dominant_envs`` etc. still work). The\ndecision-detail block (``outcome``: per-env verdicts / deltas) is\npersisted into the snapshot for internal audit but stripped from\nthis response.","operationId":"get_latest_weights_api_v1_scores_weights_latest_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/config":{"get":{"tags":["config"],"summary":"Get All Configs","description":"Get public config keys, optionally filtered by prefix.","operationId":"get_all_configs_api_v1_config_get","parameters":[{"name":"prefix","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prefix"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/config/{key}":{"get":{"tags":["config"],"summary":"Get Config","description":"Get a single public config row by key.","operationId":"get_config_api_v1_config__key__get","parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string","title":"Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/":{"get":{"tags":["health"],"summary":"Health","operationId":"health__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/health":{"get":{"tags":["health"],"summary":"Api Health","operationId":"api_health_api_v1_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}}},"components":{"schemas":{"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"MinerInfo":{"properties":{"uid":{"type":"integer","title":"Uid"},"hotkey":{"type":"string","title":"Hotkey"},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model"},"revision":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Revision"},"model_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model Type"},"is_valid":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Valid"},"challenge_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Challenge Status"},"termination_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Termination Reason"},"first_block":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"First Block"},"block_number":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Block Number"},"invalid_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Invalid Reason"},"model_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model Hash"}},"type":"object","required":["uid","hotkey"],"title":"MinerInfo","description":"Public miner metadata.\n\nBasic identity, model, validity, queue status, and commit block fields\nfor a miner."},"MinerScore":{"properties":{"miner_hotkey":{"type":"string","title":"Miner Hotkey"},"uid":{"type":"integer","title":"Uid"},"model_revision":{"type":"string","title":"Model Revision"},"model":{"type":"string","title":"Model"},"model_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model Type"},"first_block":{"type":"integer","title":"First Block"},"overall_score":{"type":"number","title":"Overall Score"},"average_score":{"type":"number","title":"Average Score"},"scores_by_env":{"additionalProperties":{"additionalProperties":true,"type":"object"},"type":"object","title":"Scores By Env"},"total_samples":{"type":"integer","title":"Total Samples"},"is_valid":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Valid"},"invalid_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Invalid Reason"},"challenge_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Challenge Status"},"termination_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Termination Reason"}},"type":"object","required":["miner_hotkey","uid","model_revision","model","first_block","overall_score","average_score","scores_by_env","total_samples"],"title":"MinerScore","description":"Score details for a miner.\n\nReflects what the new ``scorer`` writes into the ``scores`` table —\none row per miner per window with ``overall_score`` ∈ {0.0, 1.0}.\nThe CLI surfaces ``is_valid`` alongside so a miner sidelined by the\nmonitor (model_mismatch, plagiarism, …) doesn't read as competing."},"ScoresResponse":{"properties":{"block_number":{"type":"integer","title":"Block Number"},"calculated_at":{"type":"integer","title":"Calculated At"},"scores":{"items":{"$ref":"#/components/schemas/MinerScore"},"type":"array","title":"Scores"}},"type":"object","required":["block_number","calculated_at","scores"],"title":"ScoresResponse","description":"Scores snapshot response."},"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"}}}}