curl --request POST \
--url https://api.orbit.devotel.io/api/v1/quality/gamification/leaderboard \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.orbit.devotel.io/api/v1/quality/gamification/leaderboard"
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, headers=headers)
print(response.text)const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.orbit.devotel.io/api/v1/quality/gamification/leaderboard', 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.orbit.devotel.io/api/v1/quality/gamification/leaderboard",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$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.orbit.devotel.io/api/v1/quality/gamification/leaderboard"
req, _ := http.NewRequest("POST", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.orbit.devotel.io/api/v1/quality/gamification/leaderboard")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.orbit.devotel.io/api/v1/quality/gamification/leaderboard")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"data": {
"window": {
"from": "2026-08-12T09:00:00.000Z",
"to": "2026-08-19T09:00:00.000Z",
"period": "week"
},
"scope": {
"queue_id": "queue_support_l1",
"agent_ids": null
},
"rules_source": "default",
"entries": [
{
"rank": 1,
"agentId": "user_2mN4zR7Ld",
"agentName": "Dana Okafor",
"totalPoints": 337,
"breakdown": [
{
"ruleId": "calls-volume",
"label": "Calls handled",
"points": 236
},
{
"ruleId": "qa-quality",
"label": "QA score",
"points": 55
},
{
"ruleId": "csat-satisfaction",
"label": "Customer satisfaction",
"points": 26
},
{
"ruleId": "aht-efficiency",
"label": "Efficient handle time",
"points": 20
}
],
"badges": [
{
"id": "top-performer",
"name": "Top Performer",
"description": "Ranked #1 on the leaderboard for this period.",
"icon": "trophy"
},
{
"id": "qa-ace",
"name": "QA Ace",
"description": "Average QA score of 90 or higher (min. 3 evaluations).",
"icon": "shield-check"
}
],
"metrics": {
"agentId": "user_2mN4zR7Ld",
"agentName": "Dana Okafor",
"callsHandled": 118,
"avgHandleSeconds": 264,
"qaCount": 7,
"avgQaScore": 92.14,
"csatCount": 31,
"avgCsat": 4.4
}
}
]
},
"meta": {
"request_id": "req_1a2b3c4d5e",
"timestamp": "2026-08-19T09:00:00.000Z"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"status": 123,
"details": {}
},
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"docs_url": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"status": 123,
"details": {}
},
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"docs_url": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"status": 123,
"details": {}
},
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"docs_url": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"status": 123,
"details": {}
},
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"docs_url": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"status": 123,
"details": {}
},
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"docs_url": "<string>"
}
}{
"error": {
"code": "RATE_LIMITED",
"message": "<string>",
"status": 429,
"retry_after": 2
},
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"docs_url": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"status": 123,
"details": {}
},
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"docs_url": "<string>"
}
}Compute the agent leaderboard
Compute the ranked agent leaderboard for a window and scope from existing QA, call-volume and CSAT aggregates. Narrow to a team with queue_id or an explicit agent_ids allow-list, and override point_rules / badge_definitions to preview a tuned ruleset before adopting it. Supervisors are limited to their mapped queues. Reviewer scope (owner / admin / supervisor).
curl --request POST \
--url https://api.orbit.devotel.io/api/v1/quality/gamification/leaderboard \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.orbit.devotel.io/api/v1/quality/gamification/leaderboard"
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, headers=headers)
print(response.text)const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.orbit.devotel.io/api/v1/quality/gamification/leaderboard', 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.orbit.devotel.io/api/v1/quality/gamification/leaderboard",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$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.orbit.devotel.io/api/v1/quality/gamification/leaderboard"
req, _ := http.NewRequest("POST", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.orbit.devotel.io/api/v1/quality/gamification/leaderboard")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.orbit.devotel.io/api/v1/quality/gamification/leaderboard")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"data": {
"window": {
"from": "2026-08-12T09:00:00.000Z",
"to": "2026-08-19T09:00:00.000Z",
"period": "week"
},
"scope": {
"queue_id": "queue_support_l1",
"agent_ids": null
},
"rules_source": "default",
"entries": [
{
"rank": 1,
"agentId": "user_2mN4zR7Ld",
"agentName": "Dana Okafor",
"totalPoints": 337,
"breakdown": [
{
"ruleId": "calls-volume",
"label": "Calls handled",
"points": 236
},
{
"ruleId": "qa-quality",
"label": "QA score",
"points": 55
},
{
"ruleId": "csat-satisfaction",
"label": "Customer satisfaction",
"points": 26
},
{
"ruleId": "aht-efficiency",
"label": "Efficient handle time",
"points": 20
}
],
"badges": [
{
"id": "top-performer",
"name": "Top Performer",
"description": "Ranked #1 on the leaderboard for this period.",
"icon": "trophy"
},
{
"id": "qa-ace",
"name": "QA Ace",
"description": "Average QA score of 90 or higher (min. 3 evaluations).",
"icon": "shield-check"
}
],
"metrics": {
"agentId": "user_2mN4zR7Ld",
"agentName": "Dana Okafor",
"callsHandled": 118,
"avgHandleSeconds": 264,
"qaCount": 7,
"avgQaScore": 92.14,
"csatCount": 31,
"avgCsat": 4.4
}
}
]
},
"meta": {
"request_id": "req_1a2b3c4d5e",
"timestamp": "2026-08-19T09:00:00.000Z"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"status": 123,
"details": {}
},
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"docs_url": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"status": 123,
"details": {}
},
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"docs_url": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"status": 123,
"details": {}
},
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"docs_url": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"status": 123,
"details": {}
},
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"docs_url": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"status": 123,
"details": {}
},
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"docs_url": "<string>"
}
}{
"error": {
"code": "RATE_LIMITED",
"message": "<string>",
"status": 429,
"retry_after": 2
},
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"docs_url": "<string>"
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"status": 123,
"details": {}
},
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"docs_url": "<string>"
}
}Authorizations
Dashboard JWT token from Clerk
Headers
Stripe-style idempotency token. Pass a stable, client-generated value (1-255 chars) to dedupe retries on transient timeouts. The same key+credential+path replays the original response for 24h on 2xx (5min on 4xx, 30s on 5xx). Returns 409 if a concurrent request with the same key is already in flight; replayed responses include the Idempotency-Replay: true response header.
1 - 255Sandbox opt-in for Clerk-session-authenticated requests. Set to true to route the call through the test-mode pipeline: no real provider delivery, no credits deducted, response meta.test_mode: true. Ignored for live API keys (dv_live_sk_*) — server-to-server clients must use a test-prefixed key (dv_test_sk_*) to exercise sandbox. Test-prefixed keys unconditionally enable sandbox regardless of this header.
true, false Response
The ranked leaderboard for the resolved window and scope. An empty entries array means no agent in scope has data yet.