---
title: "Top users for one domain, by best AutoScientist run"
method: GET
path: "/api/v1/leaderboard"
tags: ["leaderboard"]
---

# Top users for one domain, by best AutoScientist run

`GET /api/v1/leaderboard`

## Request

- The document declares no server URL.
- Auth: HTTP bearer
- TypeScript: <https://skmtc.dev/adaptionlabs/apis/adaption-api/docs/api/v1/leaderboard/get.ts> (a function with typed inputs; its response is checked against the schema)

Public endpoint; no authentication required. Returns one row per user — that user's best-scoring run in the domain — ordered by domain win rate descending, one page at a time. Page with `limit`/`offset`: a "show more" click is the same request with `offset` advanced by the rows already on screen, and `pagination.has_more` says whether to show the control at all. Ranks are absolute over the whole ranking, so page two starts at rank 11 and ranks 1–3 identify the top three without a separate response section. `pagination.total` is the eligible population, not the rows in this page. Pass `q` to search every domain by member, run or dataset name — the same page shape, cut from the matches instead of from a single ranking, with `domain` ignored and each row naming the domain it is ranked in.

## Query parameters

- `domain` string
- `q` string
- `limit` integer
- `offset` integer

## Response `200`

- LeaderboardResponseDto
  - `domain` LeaderboardDomainDto, required
    - `code` string, nullable, required: `Domains.code`. Null for the synthetic `general` and `all` buckets.
    - `slug` string, required
    - `name` string, required
  - `pagination` LeaderboardPaginationDto, required
    - `limit` integer, required: Rows asked for — the page size actually applied.
    - `offset` integer, required: Rows skipped.
    - `total` integer, required: Ranked users in this domain, all of them — not the rows in this page. Drives "showing 10 of 137". Under `q` it is the number of matches across every domain instead.
    - `has_more` boolean, required: Whether another page exists. Show the "show more" control on true, and call again with `offset + limit`.
  - `data` LeaderboardRowDto[], required: One page of the ranking, in rank order. Empty past the end of the ranking and for a recognised domain with no ranked entries.
    - `rank` integer, required: Absolute position in the ranking, from 1 — not the index within the page. Contiguous with no gaps, so ranks 1–3 identify the top three without a separate response section.
    - `user` LeaderboardUserDto, required
      - `user_id` string, required: Stable public identifier.
      - `display_name` string, nullable, required: Profile name. Null when the profile has none; no contact detail is substituted.
      - `avatar_url` string, nullable, required: Avatar image reference. Null when the profile has none.
      - `bio` string, nullable, required: Profile biography, verbatim. Null — never an empty string — when the profile has none.
      - `country` LeaderboardCountryDto, required
        - `code` string, required: ISO country code, as stored.
        - `name` string, required
      - `links` LeaderboardUserLinksDto, required
        - `homepage` string, nullable, required: Profile homepage. Only http(s) links are served — a stored value with any other scheme reads as null, so this is safe to use as an href.
        - `github` string, nullable, required
        - `x` string, nullable, required
        - `linkedin` string, nullable, required
      - `stats` LeaderboardUserStatsDto, required
        - `submissions` integer, required: AutoScientist experiments this user has submitted, all-time and across every domain — not only the ranked ones, so it is at least 1 for anyone on the table, and 0 only when the totals read failed.
        - `best_win_rate_pct` number, nullable, required: The user's best domain win rate across every domain, as a percentage with one decimal. Usually higher than this row's `score` when the user ranks better in another domain. Null when they have no completed domain evaluation of their own, and when the totals read failed.
        - `data_points` integer, required: Training rows across every distinct dataset the user has run an experiment on, post-augmentation where augmentation ran. A raw count — the popup's "K" is formatting.
    - `model` LeaderboardModelDto, required
      - `name` string, required: This run's own model name — the same label the product shows for it in the dataset page's trained-model selection, so a member recognises their own row. Composed as `adaption_<base model>_<dataset>_<run id>`; the trailing run id is what distinguishes two runs on the same dataset. Always present: a component that cannot be resolved contributes a placeholder rather than making the whole name absent. This was previously the constant "AutoScientist" for every row. That branding is the page's, not the API's — render it alongside this name rather than expecting it here.
      - `base_model` LeaderboardBaseModelDto, required
        - `display_name` string, required
        - `family` string, nullable, required: Model family — the signal for which base-model logo to show.
        - `size` string, nullable, required
    - `alignment` boolean, required: Whether this run went through alignment training — an SFT stage followed by a DPO (preference) stage. True when the ranked run is the DPO stage of such a pipeline, or the SFT stage with a DPO stage linked to it. False for a standalone SFT run and for a one-shot DPO run with no SFT stage. Never null: a row is either aligned or it is not. Descriptive only — it does not affect eligibility, rank, or `domain_win_rate_pct`. It does determine which stage `task_win_rate_pct` comes from.
    - `score` LeaderboardScoreDto, required
      - `domain_win_rate_pct` number, required: Win rate from the run's domain evaluation against the fixed per-domain prompt set, as a percentage with one decimal. Shown for context; it is NOT the ranking metric — see `normalized_score`. Comparing it across rows favours runs on stronger base models, which is the bias the ranking score exists to remove.
      - `normalized_score` number, nullable, required: The base-adjusted score the ranking is ordered by (higher is better). It measures how far above its own base model's typical result in this domain the run lands, on a standardised (z-score-like) scale — so a Llama fine-tune and a Qwen fine-tune are judged by how much each beat its own base, not by raw win rate, which a weak base depresses no matter how good the fine-tune. 0 is a typical run for that base; +1 is about one standard deviation better. Small/thin base groups are shrunk toward the whole-domain average so a lucky one-off cannot top the board. Null only when the run has no comparable runs to be scored against.
      - `percentile` integer, nullable, required: This run's standing as a percentile of the base-adjusted score — the share of ranked runs it beats, 0–100 (94 = better than 94%). This is the `normalized_score` re-expressed for display; the ranking is ordered by the score itself. The comparison pool is the currently-viewed ranking: every ranked run in the domain (across all base models, not only the same base) for a single domain, or every ranked run of every domain for the "All Domains" aggregate. Null when the score is.
      - `task_win_rate_pct` number, nullable, required: Win rate from the experiment's own evaluation against the user's data — how well the model does at the task it was trained for. Each run is scored on a different held-out set, so this is NOT comparable between rows and nothing is ordered by it. Null for a run whose iteration evals never produced a score. For a run with `alignment: true` this is the best DPO (preference) stage's score, never the SFT stage's — so every row reports the task score of the last training stage its run completed. An alignment run whose DPO stage produced no score reads null rather than falling back to its SFT score, which would be a number measured on the wrong stage.
    - `dataset` LeaderboardDatasetDto, required
      - `name` string, nullable, required
      - `rows_before` integer, nullable, required: Rows in the source dataset, before augmentation. Null when the source dataset is gone or was never row-counted.
      - `rows_after` integer, nullable, required: Rows actually trained on: source plus whatever augmentation minted. Equal to `rows_before` when no augmentation ran, so a UI can show "12k → 44k" or a single figure by comparing the two.
      - `huggingface_url` string, nullable, required: Published dataset location on Hugging Face, when one exists.
      - `kaggle_url` string, nullable, required: Published dataset location on Kaggle, when one exists.
    - `model_huggingface_url` string, nullable, required: Published location of the run's fine-tuned MODEL on Hugging Face — not the dataset it was trained on, which carries its own links under `dataset`. Null unless an export completed successfully — a pending or failed export reads as null.
    - `model_kaggle_url` string, nullable, required: Published location of the run's fine-tuned MODEL on Kaggle — not the dataset it was trained on, which carries its own links under `dataset`. Null unless an export completed successfully — a pending or failed export reads as null.
    - `completed_at` string, date-time, nullable, required
    - `domain` LeaderboardDomainDto, required
      - `code` string, nullable, required: `Domains.code`. Null for the synthetic `general` and `all` buckets.
      - `slug` string, required
      - `name` string, required
  - `generated_at` string, date-time, nullable, required: When this ranking was computed. Matches the value the overview reports within one generation, so the selector and the table always describe the same data. The leaderboard is refreshed once a day: a run that becomes eligible after a refresh appears at the next one. The exception is a run that gives its domain its first ranked entry — a new domain is picked up within minutes rather than waiting for the next day. Null means the response was computed for this request rather than served from a refresh. Member identity — name, avatar, biography, links, country — is always current regardless of this timestamp.

## Changes

- **2026-09-22** `4e7c0cba0fd4`: 1 info
  - added the new optional `query` request parameter `q`
- **2026-09-15** `f4d1edd8f3d1`: 4 info
  - added the required property `data/items/domain` to the response with the `200` status
  - added the required property `data/items/model_kaggle_url` to the response with the `200` status
  - added the required property `data/items/score/normalized_score` to the response with the `200` status
  - added the required property `data/items/score/percentile` to the response with the `200` status

[Operation history](https://skmtc.dev/adaptionlabs/apis/adaption-api/changes/api/v1/leaderboard/get.md)

---

[API](https://skmtc.dev/adaptionlabs/apis/adaption-api.md) - [All operations](https://skmtc.dev/adaptionlabs/apis/adaption-api/llms.txt) - [OpenAPI document](https://skmtc.dev/adaptionlabs/apis/adaption-api/revisions/d4cf908c19a0?raw)
