curl --request GET \
--url https://api.closebot.com/leaderboard/metrics \
--header 'X-CB-KEY: <api-key>'import requests
url = "https://api.closebot.com/leaderboard/metrics"
headers = {"X-CB-KEY": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-CB-KEY': '<api-key>'}};
fetch('https://api.closebot.com/leaderboard/metrics', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.closebot.com/leaderboard/metrics",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-CB-KEY: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.closebot.com/leaderboard/metrics"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-CB-KEY", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.closebot.com/leaderboard/metrics")
.header("X-CB-KEY", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.closebot.com/leaderboard/metrics")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-CB-KEY"] = '<api-key>'
response = http.request(request)
puts response.read_body[
{
"key": "<string>",
"label": "<string>",
"description": "<string>",
"format": "<string>",
"higherIsBetter": true,
"supportsSourceScope": true,
"isHeadline": true,
"guidance": "<string>"
}
]The metrics a board can be ranked by. Clients should build their columns from this rather than hardcoding a list, so changing the headline set needs no frontend deploy.
curl --request GET \
--url https://api.closebot.com/leaderboard/metrics \
--header 'X-CB-KEY: <api-key>'import requests
url = "https://api.closebot.com/leaderboard/metrics"
headers = {"X-CB-KEY": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-CB-KEY': '<api-key>'}};
fetch('https://api.closebot.com/leaderboard/metrics', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.closebot.com/leaderboard/metrics",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-CB-KEY: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.closebot.com/leaderboard/metrics"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-CB-KEY", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.closebot.com/leaderboard/metrics")
.header("X-CB-KEY", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.closebot.com/leaderboard/metrics")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-CB-KEY"] = '<api-key>'
response = http.request(request)
puts response.read_body[
{
"key": "<string>",
"label": "<string>",
"description": "<string>",
"format": "<string>",
"higherIsBetter": true,
"supportsSourceScope": true,
"isHeadline": true,
"guidance": "<string>"
}
]Authorizations
CloseBot API Key Authorization
Response
OK
Wire key to pass as metric on GET /leaderboard/board.
Display name.
What the metric counts, and anything it deliberately excludes.
How to render the value: integer, decimal, duration (milliseconds), currency (USD), or score (0-100).
False when the board ranks ascending — cost, latency and error metrics, where #1 means least rather than most. Clients should say so next to the metric; a user who assumes "more is better" will read an AI-errors board exactly backwards.
False for agency-wide metrics. Requesting scope=source for one of these is a 400.
True for the metrics the board actually surfaces — the radar's axes and the table's columns, in the order they appear here. Everything else is still ranked and stored, just not shown.
One sentence on how to move this metric, for the board's headline figure.
Null outside the headline set, and clients must render nothing rather than an empty
line — widening Headline before its copy is written should degrade to silence,
not to a stray label.

