Documentation
API v1
Leaderboards
Create leaderboards that a process fills with counts, with place badges that move by themselves, and voting boards with contenders, votes, and ratings.
Working with an AI agent?or point it at the Leaderboards markdown or the full-API markdown.
List leaderboards
GET
/api/v1/leaderboards/listList the org's leaderboards and voting boards by updatedAt, oldest first, with a cursor. A board that changes during a walk moves after the cursor, thus pass updatedSince to sync only the changes. Requires leaderboards:read (or :write).
| Parameter | Type | Description |
|---|---|---|
| limit | number optional | Boards per page, 1 to 500. The default is 100. |
| cursor | string optional | The nextCursor of the previous page. |
| updatedSince | number optional | Only boards updated at or after this time, in milliseconds since 1970. |
| kind | Voting | System | Counted | Bracket optional | Only boards of this kind. |
Response:
{
data: {
id: string;
name: string;
emoji: string | null;
kind: 'Voting' | 'System' | 'Counted' | 'Bracket';
type: 'FaceOff' | 'UpDown' | 'Rate' | 'Review' | 'Leaderboard' | 'Bracket';
systemKind: 'ThanksReceived' | 'ThanksGiven' | 'ContactsParsed' | 'CompaniesParsed' | null;
description: string | null;
countLabel: string | null;
badgeMode: 'None' | 'Top1' | 'Top3';
notifyMode: 'Gains' | 'AllChanges' | 'Silent' | null;
createdByProfileId: number;
createdAt: number;
updatedAt: number;
lastActivityAt: number;
}[];
nextCursor: string | null;
}Get leaderboard
GET
/api/v1/leaderboards/getGet one board with its top 10 rows and its row total. On a read-only leaderboard the rows are entries; on a voting board they are contenders. Requires leaderboards:read (or :write).
| Parameter | Type | Description |
|---|---|---|
| id | string required | Leaderboard id. |
Response:
{
data: {
id: string;
name: string;
emoji: string | null;
kind: 'Voting' | 'System' | 'Counted' | 'Bracket';
type: 'FaceOff' | 'UpDown' | 'Rate' | 'Review' | 'Leaderboard' | 'Bracket';
systemKind: 'ThanksReceived' | 'ThanksGiven' | 'ContactsParsed' | 'CompaniesParsed' | null;
description: string | null;
countLabel: string | null;
badgeMode: 'None' | 'Top1' | 'Top3';
notifyMode: 'Gains' | 'AllChanges' | 'Silent' | null;
createdByProfileId: number;
createdAt: number;
updatedAt: number;
lastActivityAt: number;
top: {
rank: number;
kind: 'Item' | 'Member' | 'Named';
id: string;
name: string;
imageUrl?: string;
linkUrl?: string;
profileId?: number;
email?: string;
count?: number;
score?: number;
votes?: number;
ratingCount?: number;
}[];
totalRows: number;
};
}Create leaderboard
POST
/api/v1/leaderboards/createCreate a voting board (kind Voting, with a type) or a counted leaderboard that a process fills (kind Counted). The token owner is the creator. Only an admin creates a counted leaderboard with badges. Requires leaderboards:write.
| Parameter | Type | Description |
|---|---|---|
| kind | Voting | Counted required | Voting or Counted. |
| name | string required | Name of the board. |
| emoji | string optional | An emoji for the board. |
| type | FaceOff | UpDown | Rate | Review optional | Voting boards only: how people vote. The default is FaceOff. |
| description | string optional | Counted leaderboards only: a line about the board. |
| countLabel | string optional | Counted leaderboards only: the noun after a count, for example "pull requests merged". |
| notifyMode | Gains | AllChanges | Silent optional | Counted leaderboards only: who hears about a place change. The default is Gains. |
| badgeMode | None | Top1 | Top3 optional | Counted leaderboards only: badges for the top places. Needs an admin. The default is None. |
Response:
{
data: {
id: string;
name: string;
emoji: string | null;
kind: 'Voting' | 'System' | 'Counted' | 'Bracket';
type: 'FaceOff' | 'UpDown' | 'Rate' | 'Review' | 'Leaderboard' | 'Bracket';
systemKind: 'ThanksReceived' | 'ThanksGiven' | 'ContactsParsed' | 'CompaniesParsed' | null;
description: string | null;
countLabel: string | null;
badgeMode: 'None' | 'Top1' | 'Top3';
notifyMode: 'Gains' | 'AllChanges' | 'Silent' | null;
createdByProfileId: number;
createdAt: number;
updatedAt: number;
lastActivityAt: number;
};
created: true;
}Update leaderboard
POST
/api/v1/leaderboards/updateChange a board. A voting board takes name, emoji, and type. A counted leaderboard takes name, emoji, description, countLabel, notifyMode, and badgeMode. An OrgOrg leaderboard takes name, emoji, and badgeMode. A badge mode needs an admin. An omitted field stays the same. Requires leaderboards:write.
| Parameter | Type | Description |
|---|---|---|
| id | string required | Leaderboard id. |
| name | string optional | New name. |
| emoji | string optional | New emoji. |
| type | FaceOff | UpDown | Rate | Review optional | Voting boards only: the new voting style. Each contender gets a new score. |
| description | string optional | Counted leaderboards only. An empty string clears it. |
| countLabel | string optional | Counted leaderboards only. An empty string clears it. |
| notifyMode | Gains | AllChanges | Silent optional | Read-only leaderboards only: who hears about a place change. |
| badgeMode | None | Top1 | Top3 optional | Read-only leaderboards only: badges for the top places. Needs an admin. The badges move at once. |
Response:
{
data: {
id: string;
name: string;
emoji: string | null;
kind: 'Voting' | 'System' | 'Counted' | 'Bracket';
type: 'FaceOff' | 'UpDown' | 'Rate' | 'Review' | 'Leaderboard' | 'Bracket';
systemKind: 'ThanksReceived' | 'ThanksGiven' | 'ContactsParsed' | 'CompaniesParsed' | null;
description: string | null;
countLabel: string | null;
badgeMode: 'None' | 'Top1' | 'Top3';
notifyMode: 'Gains' | 'AllChanges' | 'Silent' | null;
createdByProfileId: number;
createdAt: number;
updatedAt: number;
lastActivityAt: number;
};
}Delete leaderboard
POST
/api/v1/leaderboards/deleteDelete a board with its entries, contenders, votes, and ratings. A voting board: its creator. A counted leaderboard: its creator or an admin, and only an admin when it awards badges; its badges close. An OrgOrg leaderboard: an admin. Requires leaderboards:write.
| Parameter | Type | Description |
|---|---|---|
| id | string required | Leaderboard id. |
Response:
{
data: { id: string };
deleted: true;
}List entries
GET
/api/v1/leaderboards/entries/listList the entries of a read-only leaderboard in rank order: the highest count first, then the entry that reached its count first. A member the org suspended is left out, thus a page can hold fewer entries than the limit. Requires leaderboards:read (or :write).
| Parameter | Type | Description |
|---|---|---|
| id | string required | Leaderboard id. |
| limit | number optional | Entries per page, 1 to 500. The default is 100. |
| cursor | string optional | The nextCursor of the previous page. |
Response:
{
data: {
rank: number;
id: string;
kind: 'Member' | 'Named';
key: string; // member:<profileId> for a member
count: number;
countChangedAt: number;
name: string;
imageUrl: string | null;
linkUrl: string | null;
profileId: number | null;
email: string | null;
}[];
nextCursor: string | null;
}Upsert entries
POST
/api/v1/leaderboards/entries/upsertCreate or update entries of a counted leaderboard by key, up to 500 per request. A key is trimmed and in lowercase. An entry not in the request keeps its row. The answer has one result per entry, and one bad entry does not stop the others. An identical request writes nothing and answers Unchanged for each entry. On a board with badges, only an admin sends entries, and the badges move 5 minutes after the order changes. Requires leaderboards:write.
| Parameter | Type | Description |
|---|---|---|
| id | string required | Leaderboard id. |
| entries | object required | An array of entries. A member: { member: { email } or { profileId }, count }. A named entry: { key, name, imageUrl?, linkUrl?, count }. A count is a whole number, 0 or more. |
Response:
{
data: {
results: {
index: number;
key: string | null;
status: 'Created' | 'Updated' | 'Unchanged' | 'Deleted' | 'NotFound' | 'Rejected';
error?: string;
}[];
orderChanged: boolean;
};
}Replace entries
POST
/api/v1/leaderboards/entries/replaceMake a counted leaderboard hold exactly these entries, 1 to 1000. A row not in the request is deleted, except the row of an entry that the request sends with an error. Requires leaderboards:write.
| Parameter | Type | Description |
|---|---|---|
| id | string required | Leaderboard id. |
| entries | object required | An array of entries. A member: { member: { email } or { profileId }, count }. A named entry: { key, name, imageUrl?, linkUrl?, count }. A count is a whole number, 0 or more. |
Response:
{
data: {
results: {
index: number;
key: string | null;
status: 'Created' | 'Updated' | 'Unchanged' | 'Deleted' | 'NotFound' | 'Rejected';
error?: string;
}[];
orderChanged: boolean;
deleted: number;
};
}Delete entries
POST
/api/v1/leaderboards/entries/deleteDelete entries of a counted leaderboard by key or by member, up to 1000. A member in any status can be removed. Requires leaderboards:write.
| Parameter | Type | Description |
|---|---|---|
| id | string required | Leaderboard id. |
| entries | object required | An array of { key } or { member: { email } or { profileId } }. |
Response:
{
data: {
results: {
index: number;
key: string | null;
status: 'Created' | 'Updated' | 'Unchanged' | 'Deleted' | 'NotFound' | 'Rejected';
error?: string;
}[];
orderChanged: boolean;
};
}List contenders
GET
/api/v1/leaderboards/contenders/listList the contenders of a voting board, best score first, then the most rated. The score is the Elo rating on a face-off board, the net vote on an up/down board, and the average stars on a star board. Requires leaderboards:read (or :write).
| Parameter | Type | Description |
|---|---|---|
| id | string required | Leaderboard id. |
Response:
{
data: ({
id: string;
leaderboardId: string;
name: string;
description: string | null;
imageUrl: string | null;
linkUrl: string | null;
mapsUrl: string | null;
score: number; // the Elo rating, the net vote, or the average stars
eloRating: number;
matchupVotes: number;
ratingSum: number;
ratingCount: number;
addedByProfileId: number;
createdAt: number;
} & { rank: number })[];
}Add contender
POST
/api/v1/leaderboards/contenders/createAdd a contender to a voting board. A board holds at most 500 contenders. Requires leaderboards:write.
| Parameter | Type | Description |
|---|---|---|
| id | string required | Leaderboard id. |
| name | string required | Name of the contender. |
| description | string optional | A short description. |
| imageUrl | string optional | An image URL. |
| linkUrl | string optional | A link URL. |
| mapsUrl | string optional | A Google Maps URL. |
Response:
{
data: {
id: string;
leaderboardId: string;
name: string;
description: string | null;
imageUrl: string | null;
linkUrl: string | null;
mapsUrl: string | null;
score: number; // the Elo rating, the net vote, or the average stars
eloRating: number;
matchupVotes: number;
ratingSum: number;
ratingCount: number;
addedByProfileId: number;
createdAt: number;
};
created: true;
}Update contender
POST
/api/v1/leaderboards/contenders/updateChange a contender. The person who added it or the board creator. An omitted field stays the same, and an empty string clears an optional field. Requires leaderboards:write.
| Parameter | Type | Description |
|---|---|---|
| id | string required | Contender id. |
| name | string optional | New name. |
| description | string optional | New description. |
| imageUrl | string optional | New image URL. |
| linkUrl | string optional | New link URL. |
| mapsUrl | string optional | New Google Maps URL. |
Response:
{
data: {
id: string;
leaderboardId: string;
name: string;
description: string | null;
imageUrl: string | null;
linkUrl: string | null;
mapsUrl: string | null;
score: number; // the Elo rating, the net vote, or the average stars
eloRating: number;
matchupVotes: number;
ratingSum: number;
ratingCount: number;
addedByProfileId: number;
createdAt: number;
};
}Delete contender
POST
/api/v1/leaderboards/contenders/deleteDelete a contender with its votes and ratings. The person who added it or the board creator. Requires leaderboards:write.
| Parameter | Type | Description |
|---|---|---|
| id | string required | Contender id. |
Response:
{
data: { id: string };
deleted: true;
}Cast face-off vote
POST
/api/v1/leaderboards/votes/castRecord a face-off vote: the winner beats the loser, and both Elo ratings move. Both contenders must be on the same face-off board. Requires leaderboards:write.
| Parameter | Type | Description |
|---|---|---|
| winnerId | string required | The contender that wins. |
| loserId | string required | The contender that loses. |
Response:
{
data: {
winner: {
id: string;
leaderboardId: string;
name: string;
description: string | null;
imageUrl: string | null;
linkUrl: string | null;
mapsUrl: string | null;
score: number; // the Elo rating, the net vote, or the average stars
eloRating: number;
matchupVotes: number;
ratingSum: number;
ratingCount: number;
addedByProfileId: number;
createdAt: number;
};
loser: {
id: string;
leaderboardId: string;
name: string;
description: string | null;
imageUrl: string | null;
linkUrl: string | null;
mapsUrl: string | null;
score: number; // the Elo rating, the net vote, or the average stars
eloRating: number;
matchupVotes: number;
ratingSum: number;
ratingCount: number;
addedByProfileId: number;
createdAt: number;
};
};
}Set rating
POST
/api/v1/leaderboards/ratings/setSet the token owner's vote on an up/down board (1 or -1) or rating on a star board (1 to 5), with a review on a Review board. A second call changes the owner's rating; it does not add one. Requires leaderboards:write.
| Parameter | Type | Description |
|---|---|---|
| contenderId | string required | Contender id. |
| value | number required | 1 or -1 on an up/down board, 1 to 5 on a star board. |
| review | string optional | Review boards only: the review text. |
Response:
{
data: {
id: string;
leaderboardId: string;
name: string;
description: string | null;
imageUrl: string | null;
linkUrl: string | null;
mapsUrl: string | null;
score: number; // the Elo rating, the net vote, or the average stars
eloRating: number;
matchupVotes: number;
ratingSum: number;
ratingCount: number;
addedByProfileId: number;
createdAt: number;
};
}