> For the complete documentation index, see [llms.txt](https://docs.domino.run/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.domino.run/docs/developer-resources/portal-leaderboard-api.md).

# Portal Leaderboard API

The Leaderboard API lets you retrieve your community's merged leaderboard rankings and look up individual user positions. All leaderboard data is aggregated across every visible leaderboard in your community.

## Overview

Use the Leaderboard API to:

* Display leaderboard rankings in your own UI or application
* Look up a specific user's rank and points by user ID
* Look up a user by social ID or username (Discord, Twitter, Telegram, Reddit, email, etc.)
* Filter rankings by time period (daily, weekly, bi-weekly, monthly, or all-time)
* Paginate through large leaderboards with cursor-based pagination

## Authentication

All Leaderboard API requests require a **Community API Key** passed in the `x-api-key` header. You can create Community API Keys from your community dashboard.

```
x-api-key: <community-api-key>
```

{% hint style="info" %}
Replace `your-community` in the URLs below with your community slug. For example, if your portal is at `acme.domino.page`, your slug is `acme`.
{% endhint %}

***

## Get Leaderboard Rankings

Retrieves the full leaderboard with all users ranked by the default leaderboard, including per-leaderboard point breakdowns.

```
GET https://your-community.domino.page/api/v1/leaderboard
```

### Query Parameters

| Parameter       | Type   | Required | Description                                                                                           |
| --------------- | ------ | -------- | ----------------------------------------------------------------------------------------------------- |
| `limit`         | Number | No       | Number of users to return per page (1–100, default `20`)                                              |
| `cursor`        | Number | No       | Pagination cursor returned from a previous request. Omit for the first page                           |
| `view`          | String | No       | Time period filter. One of `all_time`, `daily`, `weekly`, `bi_weekly`, `monthly` (default `all_time`) |
| `leaderboardId` | String | No       | Rank by this leaderboard instead of the default one. Must be a visible leaderboard in your community  |

### Response

| Property                           | Type    | Description                                                                                                         |
| ---------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------- |
| `leaderboards`                     | Array   | All visible leaderboards for the community                                                                          |
| `leaderboards[].id`                | String  | Leaderboard ID                                                                                                      |
| `leaderboards[].name`              | String  | Leaderboard name                                                                                                    |
| `leaderboards[].portalColumnLabel` | String  | Custom column label displayed in the portal (may be `null`)                                                         |
| `leaderboards[].isDefault`         | Boolean | Whether this is the default leaderboard used for ranking                                                            |
| `users`                            | Array   | Ranked list of users                                                                                                |
| `users[].user`                     | Object  | User profile                                                                                                        |
| `users[].user.id`                  | String  | User ID                                                                                                             |
| `users[].user.name`                | String  | Display name                                                                                                        |
| `users[].user.imageUrl`            | String  | Profile image URL (may be `null`)                                                                                   |
| `users[].rank`                     | Number  | User's rank based on the default leaderboard                                                                        |
| `users[].pointsByLeaderboard`      | Object  | Points keyed by leaderboard ID, e.g. `{ "lb-id-1": 500, "lb-id-2": 120 }`                                           |
| `users[].rankByLeaderboard`        | Object  | Rank keyed by leaderboard ID, e.g. `{ "lb-id-1": 1, "lb-id-2": 3 }`                                                 |
| `users[].tierData`                 | Object  | The user's tier on the ranking leaderboard, or `null` if that leaderboard has tiers turned off. See [Tiers](#tiers) |
| `nextCursor`                       | Number  | Cursor value for the next page, or `null` if there are no more results                                              |
| `hasMore`                          | Boolean | Whether more results are available                                                                                  |

### Example Response

```json
{
  "leaderboards": [
    {
      "id": "lb-abc123",
      "name": "Main Leaderboard",
      "portalColumnLabel": "XP",
      "isDefault": true,
      "startDate": null,
      "endDate": null
    },
    {
      "id": "lb-def456",
      "name": "Bonus Points",
      "portalColumnLabel": "Bonus",
      "isDefault": false,
      "startDate": null,
      "endDate": null
    }
  ],
  "users": [
    {
      "user": {
        "id": "user-001",
        "name": "Alice",
        "imageUrl": "https://cdn.example.com/alice.png"
      },
      "rank": 1,
      "pointsByLeaderboard": {
        "lb-abc123": 1500,
        "lb-def456": 300
      },
      "rankByLeaderboard": {
        "lb-abc123": 1,
        "lb-def456": 3
      }
    },
    {
      "user": {
        "id": "user-002",
        "name": "Bob",
        "imageUrl": null
      },
      "rank": 2,
      "pointsByLeaderboard": {
        "lb-abc123": 1200,
        "lb-def456": 450
      },
      "rankByLeaderboard": {
        "lb-abc123": 2,
        "lb-def456": 1
      }
    }
  ],
  "nextCursor": 2,
  "hasMore": true
}
```

### Example Request

```javascript
const response = await fetch('https://acme.domino.page/api/v1/leaderboard?limit=10&view=weekly', {
  headers: {
    'x-api-key': 'your-community-api-key'
  }
});

const leaderboard = await response.json();
console.log(leaderboard.users); // Top 10 users for this week
```

### Paginating Through Results

```javascript
async function getAllRankings() {
  const allUsers = [];
  let cursor = undefined;

  do {
    const params = new URLSearchParams({ limit: '100' });
    if (cursor) params.set('cursor', String(cursor));

    const response = await fetch(
      `https://acme.domino.page/api/v1/leaderboard?${params}`,
      { headers: { 'x-api-key': 'your-community-api-key' } }
    );

    const page = await response.json();
    allUsers.push(...page.users);
    cursor = page.nextCursor;
  } while (cursor);

  return allUsers;
}
```

***

## Get User Ranking

Retrieves a single user's rank and points across all visible leaderboards.

```
GET https://your-community.domino.page/api/v1/leaderboard/:userId
```

### Path Parameters

| Parameter | Type   | Required | Description   |
| --------- | ------ | -------- | ------------- |
| `userId`  | String | Yes      | The user's ID |

### Query Parameters

| Parameter       | Type   | Required | Description                                                                                           |
| --------------- | ------ | -------- | ----------------------------------------------------------------------------------------------------- |
| `view`          | String | No       | Time period filter. One of `all_time`, `daily`, `weekly`, `bi_weekly`, `monthly` (default `all_time`) |
| `leaderboardId` | String | No       | Rank by this leaderboard instead of the default one. Must be a visible leaderboard in your community  |

### Response

| Property              | Type   | Description                                                                                                         |
| --------------------- | ------ | ------------------------------------------------------------------------------------------------------------------- |
| `user`                | Object | User profile                                                                                                        |
| `user.id`             | String | User ID                                                                                                             |
| `user.name`           | String | Display name                                                                                                        |
| `user.imageUrl`       | String | Profile image URL (may be `null`)                                                                                   |
| `rank`                | Number | User's rank based on the default leaderboard                                                                        |
| `pointsByLeaderboard` | Object | Points keyed by leaderboard ID, e.g. `{ "lb-id-1": 500, "lb-id-2": 120 }`                                           |
| `rankByLeaderboard`   | Object | Rank keyed by leaderboard ID, e.g. `{ "lb-id-1": 1, "lb-id-2": 3 }`                                                 |
| `tierData`            | Object | The user's tier on the ranking leaderboard, or `null` if that leaderboard has tiers turned off. See [Tiers](#tiers) |

### Example Response

```json
{
  "user": {
    "id": "user-001",
    "name": "Alice",
    "imageUrl": "https://cdn.example.com/alice.png"
  },
  "rank": 1,
  "pointsByLeaderboard": {
    "lb-abc123": 1500,
    "lb-def456": 300
  },
  "rankByLeaderboard": {
    "lb-abc123": 1,
    "lb-def456": 3
  },
  "tierData": {
    "level": 12,
    "tier": { "name": "Silver", "color": "slate" },
    "xpForCurrentLevel": 1440,
    "xpForNextLevel": 1690,
    "xpProgress": 24
  }
}
```

### Example Request

```javascript
const userId = 'user-001';
const response = await fetch(`https://acme.domino.page/api/v1/leaderboard/${userId}?view=monthly`, {
  headers: {
    'x-api-key': 'your-community-api-key'
  }
});

const ranking = await response.json();
console.log(`Rank #${ranking.rank}`);
```

***

## Look Up User Ranking by Social ID

Finds a user by a social platform ID or username and returns their ranking. This is useful when you don't have the Domino user ID but know the user's social identity.

```
GET https://your-community.domino.page/api/v1/leaderboard/lookup
```

At least one identifier query parameter is required. If multiple identifiers are provided, a user matching **any** of them will be returned.

### Query Parameters — Identifiers

| Parameter          | Type   | Description                  |
| ------------------ | ------ | ---------------------------- |
| `discordId`        | String | Discord user ID              |
| `discordUsername`  | String | Discord username             |
| `twitterId`        | String | Twitter/X user ID            |
| `twitterUsername`  | String | Twitter/X username           |
| `telegramId`       | String | Telegram user ID             |
| `telegramUsername` | String | Telegram username            |
| `redditId`         | String | Reddit user ID               |
| `redditUsername`   | String | Reddit username              |
| `externalId`       | String | External ID from your system |
| `email`            | String | User's email address         |

### Query Parameters — Options

| Parameter       | Type   | Required | Description                                                                                           |
| --------------- | ------ | -------- | ----------------------------------------------------------------------------------------------------- |
| `view`          | String | No       | Time period filter. One of `all_time`, `daily`, `weekly`, `bi_weekly`, `monthly` (default `all_time`) |
| `leaderboardId` | String | No       | Rank by this leaderboard instead of the default one. Must be a visible leaderboard in your community  |

### Response

The response shape is the same as [Get User Ranking](#get-user-ranking).

### Example Response

```json
{
  "user": {
    "id": "user-001",
    "name": "Alice",
    "imageUrl": "https://cdn.example.com/alice.png"
  },
  "rank": 1,
  "pointsByLeaderboard": {
    "lb-abc123": 1500,
    "lb-def456": 300
  },
  "rankByLeaderboard": {
    "lb-abc123": 1,
    "lb-def456": 3
  },
  "tierData": {
    "level": 12,
    "tier": { "name": "Silver", "color": "slate" },
    "xpForCurrentLevel": 1440,
    "xpForNextLevel": 1690,
    "xpProgress": 24
  }
}
```

### Example Requests

**Look up by Discord ID:**

```javascript
const response = await fetch(
  'https://acme.domino.page/api/v1/leaderboard/lookup?discordId=123456789012345678',
  { headers: { 'x-api-key': 'your-community-api-key' } }
);

const ranking = await response.json();
console.log(`Rank #${ranking.rank}`);
```

**Look up by Twitter username:**

```javascript
const response = await fetch(
  'https://acme.domino.page/api/v1/leaderboard/lookup?twitterUsername=alice_dev',
  { headers: { 'x-api-key': 'your-community-api-key' } }
);
```

**Look up by email with weekly view:**

```javascript
const response = await fetch(
  'https://acme.domino.page/api/v1/leaderboard/lookup?email=alice@example.com&view=weekly',
  { headers: { 'x-api-key': 'your-community-api-key' } }
);
```

**Look up by external ID (your system's user ID):**

```javascript
const response = await fetch(
  'https://acme.domino.page/api/v1/leaderboard/lookup?externalId=usr_abc123',
  { headers: { 'x-api-key': 'your-community-api-key' } }
);
```

***

## Tiers

If a leaderboard has tiers turned on (in the leaderboard settings), every ranking response includes `tierData` for the ranking leaderboard. That's the default leaderboard, or the one passed as `leaderboardId`. It matches the tier shown in your portal. When tiers are off, `tierData` is `null`.

| Property                     | Type   | Description                                                  |
| ---------------------------- | ------ | ------------------------------------------------------------ |
| `tierData.level`             | Number | The user's level                                             |
| `tierData.tier`              | Object | The tier for that level (`null` if no tier covers the level) |
| `tierData.tier.name`         | String | Tier name, e.g. `Gold`                                       |
| `tierData.tier.color`        | String | Tier color as configured, e.g. `yellow`                      |
| `tierData.xpForCurrentLevel` | Number | Points needed to reach the current level                     |
| `tierData.xpForNextLevel`    | Number | Points needed to reach the next level                        |
| `tierData.xpProgress`        | Number | Progress towards the next level, in percent (0–100)          |

{% hint style="info" %}
Tiers are calculated from the user's points on the ranking leaderboard in the selected `view`. Use `view=all_time` (the default) for the user's overall tier.
{% endhint %}

***

## Error Responses

All endpoints return standard error responses:

| Status | Description                                      |
| ------ | ------------------------------------------------ |
| `400`  | Missing required parameters (e.g. no identifier) |
| `401`  | Missing or invalid API key                       |
| `404`  | Community or user not found                      |
| `500`  | Internal server error                            |

```json
{
  "error": "User not found in leaderboard"
}
```

***

## Related Resources

* [Portal API integration guide](/docs/developer-resources/portal-api-integration-guide.md)
* [Authenticating users with the portal API](/docs/developer-resources/authenticating-users-with-the-portal-api.md)
* [Create Leaderboards](/docs/domino-portal/creating-leaderboards.md)
