> ## Documentation Index
> Fetch the complete documentation index at: https://developers.closebot.com/llms.txt
> Use this file to discover all available pages before exploring further.

# One leaderboard: the leaders, the caller's neighbourhood, and where the caller stands.



## OpenAPI

````yaml https://megastream25-api.closebot.com/swagger/v1/swagger.json get /leaderboard/board
openapi: 3.0.4
info:
  title: CloseBot API
  version: v1
servers:
  - url: https://api.closebot.com
    description: CloseBot API Endpoint
security:
  - Key: []
tags:
  - name: Account
  - name: AccountNotification
  - name: Agency
  - name: Analytics
  - name: Billing
  - name: Bot
  - name: BotMetric
  - name: BotSourceVariable
  - name: BotTemplate
  - name: BotTesting
  - name: Dashboard
  - name: Hierarchy
  - name: Lead
  - name: Leaderboard
  - name: Library
  - name: LiveDemo
  - name: Notification
  - name: Persona
  - name: Report
  - name: SmartFAQ
  - name: Source
  - name: SourceChannel
  - name: Webhook
paths:
  /leaderboard/board:
    get:
      tags:
        - Leaderboard
      summary: >-
        One leaderboard: the leaders, the caller's neighbourhood, and where the
        caller stands.
      parameters:
        - name: scope
          in: query
          description: '"source" ranks individual sources, "agency" ranks whole accounts.'
          schema:
            type: string
            default: source
        - name: metric
          in: query
          description: A key from GET /leaderboard/metrics.
          schema:
            type: string
            default: bookings
        - name: compare
          in: query
          description: >-
            Who to rank against: "all" (default), or "industry" for the
            subject's own vertical.
                        
            A mode, not an industry key. The server resolves which vertical the
            subject belongs to, so

            a caller can ask to be compared within it without ever learning — or
            naming — which one it

            is. Not valid with scope=agency: industry is a property of a source.
            Falls back to "all"

            when no board was published for the subject's vertical this period,
            which

            Closebot.Api.Controllers.LeaderboardController.GetBoardResponse.IndustryAvailable
            reports.
          schema:
            type: string
            default: all
        - name: period
          in: query
          description: '"current" (default) or "previous".'
          schema:
            type: string
            default: current
        - name: entityId
          in: query
          description: >-
            Which of the caller's own entities
            Closebot.Api.Controllers.LeaderboardController.GetBoardResponse.Me,

            Closebot.Api.Controllers.LeaderboardController.GetBoardResponse.Around
            and the eligibility describe. Defaults to their

            best-placed one. Ignored at agency scope, where the caller has
            exactly one entity. A source

            belonging to another agency is rejected.
          schema:
            type: string
        - name: limit
          in: query
          description: How many leaders to return. 1-10, default 10.
          schema:
            type: integer
            format: int32
            default: 10
        - name: around
          in: query
          description: How many neighbours either side of the caller. 0-5, default 5.
          schema:
            type: integer
            format: int32
            default: 5
      responses:
        '200':
          description: OK
          content:
            text/plain:
              schema:
                $ref: '#/components/schemas/GetBoardResponse'
            application/json:
              schema:
                $ref: '#/components/schemas/GetBoardResponse'
            text/json:
              schema:
                $ref: '#/components/schemas/GetBoardResponse'
components:
  schemas:
    GetBoardResponse:
      required:
        - around
        - cohort
        - eligibility
        - industryAvailable
        - period
        - top
      type: object
      properties:
        period:
          $ref: '#/components/schemas/LeaderboardPeriodDto'
        cohort:
          $ref: '#/components/schemas/LeaderboardCohortDto'
        industryAvailable:
          type: boolean
          description: >-
            Whether a same-industry board exists for this subject, metric and
            period — and so

            whether that comparison can be chosen.
                        
            Deliberately a boolean. Answering "is there one" is the whole of
            what a client needs;

            answering "which one" is the disclosure this endpoint will not make.
        industryLockReason:
          type: string
          description: >-
            Why the comparison cannot be chosen, when it cannot. Null when it
            can.
                        
            `"needsVolume"` — the source has not been seen enough for us to
            classify it yet,

            and
            Closebot.Api.Controllers.LeaderboardController.GetBoardResponse.IndustryMessagesCurrent
            counts toward

            Closebot.Api.Controllers.LeaderboardController.GetBoardResponse.IndustryMessagesRequired.
                        
            `"notYet"` — anything else, and deliberately incurious. A source can
            be past the

            threshold but waiting on the next batch, examined and found
            unclassifiable, classified

            too tentatively to publish, or classified fine but in a vertical
            with too few ranked

            participants to build a board from. The client is told the
            comparison is unavailable

            and not invited to guess which — the last of those cases in
            particular would hint at

            how many participants a vertical has.
          nullable: true
        industryMessagesCurrent:
          type: integer
          description: >-
            Inbound messages this source has, when
            Closebot.Api.Controllers.LeaderboardController.GetBoardResponse.IndustryLockReason
            is

            `"needsVolume"`. The caller's own figure for their own source.
          format: int64
          nullable: true
        industryMessagesRequired:
          type: integer
          description: >-
            Inbound messages needed before a first classification is attempted,
            when

            Closebot.Api.Controllers.LeaderboardController.GetBoardResponse.IndustryLockReason
            is `"needsVolume"`.
          format: int64
          nullable: true
        top:
          type: array
          items:
            $ref: '#/components/schemas/LeaderboardEntryDto'
          description: The leading entities, for the podium and the top-of-board view.
          nullable: true
        around:
          type: array
          items:
            $ref: '#/components/schemas/LeaderboardEntryDto'
          description: >-
            The window around the caller's best-placed entity. Empty when the
            caller is not on

            this board. This, not
            Closebot.Api.Controllers.LeaderboardController.GetBoardResponse.Top,
            is the view most users should land on — the

            next rank up has to look reachable.
          nullable: true
        me:
          $ref: '#/components/schemas/LeaderboardStandingDto'
        eligibility:
          $ref: '#/components/schemas/LeaderboardEligibilityDto'
      additionalProperties: false
    LeaderboardPeriodDto:
      required:
        - key
        - start
      type: object
      properties:
        key:
          type: string
          description: 'Wire value to pass back as `period`: "current" or "previous".'
          nullable: true
        start:
          type: string
          description: First instant of the period, UTC.
          format: date-time
      additionalProperties: false
      description: >-
        The calendar month a board covers.
                    
        Start and key only. The period type was always "month", the end is
        always one month past

        the start, and the client formats its own month label in the user's
        locale — a server-side

        "September 2026" is English for everybody.
    LeaderboardCohortDto:
      required:
        - kind
      type: object
      properties:
        kind:
          type: string
          description: '"global" or "industry".'
          nullable: true
      additionalProperties: false
      description: The peer group a rank is relative to.
    LeaderboardEntryDto:
      required:
        - cells
        - direction
        - displayName
        - isMine
        - value
      type: object
      properties:
        rank:
          type: integer
          description: 1-10 in `top`. Null everywhere else.
          format: int32
          nullable: true
        direction:
          type: string
          description: >-
            Which way this entity moved since last month, without the magnitude
            — "up", "down",

            "flat" or "new".
                        
            The magnitude is withheld because it is a rank in disguise: a row at
            rank 3 that moved

            up 136 was at rank 139 last month, which is a lower bound on last
            month's population.

            The caller's own movement keeps its number, because it pairs with no
            rank.
          nullable: true
        displayName:
          type: string
          description: >-
            The owning account's username, or "Anonymous". Together with

            Closebot.Api.Controllers.LeaderboardController.LeaderboardEntryDto.ImageUrl
            this is the identity a row carries for anyone outside the

            owning agency; real source and agency names still never cross a
            tenant boundary.
          nullable: true
        imageUrl:
          type: string
          description: >-
            The owning account's Clerk profile photo, for the avatar the board
            renders in place of

            a rank numeral.
                        
            Null on rows that fall back to
            Closebot.Api.Controllers.LeaderboardController.AnonymousDisplayName
            — an account that

            never set a username has not opted into a public identity, and
            attaching its owner's

            face would undo that fallback — and null whenever the Clerk lookup
            fails, which the

            client renders as initials.
          nullable: true
        value:
          type: number
          format: double
        isMine:
          type: boolean
          description: True when this row belongs to the requesting agency.
        entityId:
          type: string
          description: >-
            Which of the caller's own entities this row is. Populated under the
            same rule as

            Closebot.Api.Controllers.LeaderboardController.LeaderboardEntryDto.OwnName
            — only when
            Closebot.Api.Controllers.LeaderboardController.LeaderboardEntryDto.IsMine
            is true — and it is the caller's

            own id, so it says nothing about anyone else.
                        
            Needed because
            Closebot.Api.Controllers.LeaderboardController.LeaderboardEntryDto.IsMine
            is agency-level: several of the caller's sources

            can share one window, so "this row is mine" does not identify the
            one they asked about.
          nullable: true
        ownName:
          type: string
          description: >-
            The entity's real name — the source name at source scope, the agency
            name at agency

            scope. Populated only when
            Closebot.Api.Controllers.LeaderboardController.LeaderboardEntryDto.IsMine
            is true: a source name is usually the

            client's business name, and neither it nor an agency name may cross
            a tenant

            boundary. Everyone else has only
            Closebot.Api.Controllers.LeaderboardController.LeaderboardEntryDto.DisplayName.
          nullable: true
        cells:
          type: object
          additionalProperties:
            $ref: '#/components/schemas/LeaderboardCellDto'
          description: >-
            This entity's standing on every headline metric, keyed by metric
            key. A key is absent

            when the entity is not ranked for that metric — which is a real
            state ("not enough

            data to place them"), distinct from placing last, and is rendered as
            a gap rather

            than a zero.
          nullable: true
      additionalProperties: false
      description: >-
        One placed entity on a board.
                    
        Carries a rank only inside `top`, where the rank is 1-10 by construction
        and reveals

        nothing about the population. It never carries a percentile: a rank and
        a percentile for

        the same entity are two equations in `(rank, N)` and solve for the
        cohort size.
    LeaderboardStandingDto:
      required:
        - entityId
        - percentile
        - value
      type: object
      properties:
        percentile:
          type: number
          format: double
        value:
          type: number
          format: double
        entityId:
          type: string
          description: Source id at source scope, agency id at agency scope.
          nullable: true
      additionalProperties: false
      description: >-
        Where the caller sits on this board.
                    
        A percentile and a movement, never an absolute rank — a rank alongside
        the percentile

        solves for the cohort size, and a rank on its own still tells the
        worst-placed tenant

        roughly how many there are.
    LeaderboardEligibilityDto:
      required:
        - current
        - isEligible
        - minimum
      type: object
      properties:
        isEligible:
          type: boolean
        reason:
          type: string
          description: >-
            Machine-readable cause when not eligible: "belowVolumeFloor",
            "noIndustryLabel",

            "notComputedYet". Null when eligible.
          nullable: true
        minimum:
          type: integer
          description: Unique leads needed this period to be ranked.
          format: int32
        current:
          type: number
          description: Unique leads the caller has so far this period.
          format: double
      additionalProperties: false
      description: Why the caller is or is not on a board.
    LeaderboardCellDto:
      required:
        - value
      type: object
      properties:
        value:
          type: number
          format: double
      additionalProperties: false
      description: >-
        One entity's standing on one metric, as carried inside a board row.
                    
        The value only. Rank, percentile and participant count all previously
        rode along here on

        every row of every request — roughly five hundred (rank, percentile)
        pairs per call, which

        is more than enough to pin the population by intersection.
  securitySchemes:
    Key:
      type: apiKey
      description: CloseBot API Key Authorization
      name: X-CB-KEY
      in: header

````