---
title: "List resellers"
description: "Return a keyset-paginated list of every reseller under the panel, with billing summary embedded in each row."
---

# List resellers

Return every reseller currently registered on the panel, in ascending order by numeric ID. The response is keyset-paginated with a stable `next_cursor`, and each row already carries the billing summary (mode, credits, slot count, active users), so the typical monthly reconciliation loop does not need a second call per reseller.

This is the endpoint your back-office code uses to walk the whole tree. It only returns direct rows from the `reg_users` table, so descendants of sub-resellers appear as their own top-level entries. Rebuild the hierarchy client-side from `member_group_id` and `owner_id` if you need it.

## Endpoint

`GET https://<your-panel-domain>/panel-api/v1/resellers`

## Authentication

Send the API key in the `Authorization: Bearer <your-api-key>` header. Only admin keys can call this endpoint. Reseller keys never receive the `resellers:read` scope at issuance time, so the request is rejected with `insufficient_scope`.

## Required scope

`resellers:read`

## Query parameters

| Name | Type | Required | Default | Description |
| ---- | ---- | -------- | ------- | ----------- |
| `limit` | int | no | `50` | Page size. Clamped to `[1, 100]`. |
| `cursor` | int | no | `0` | Last ID from the previous page. Rows with `id > cursor` are returned. |
| `member_group_id` | int | no | | Restrict the list to a single member group (for example, only the `RESELLER` tier). |
| `status` | bool | no | | Filter by account status. `1` returns active accounts, `0` returns disabled ones. |
| `username` | string | no | | Exact username match. Case-sensitive. Useful when your billing system stores usernames and needs to resolve one to an ID before calling `POST /resellers/{id}/billing/adjust`. |

## Response

The response is an envelope with two fields. `items` is the page of resellers. `next_cursor` is the ID to pass as `cursor` on the next call, or `null` when you have reached the last page.

`active_users` is populated only for resellers in `users` billing mode. For `credits`-mode resellers it is always `null`. `created_at` is a Unix timestamp in seconds, or `null` for historical rows migrated before that column was added.

```json
{
  "items": [
    {
      "id": 100234567,
      "username": "reseller_alice",
      "email": "alice@example.com",
      "member_group_id": 4,
      "member_group_name": "RESELLER",
      "status": 1,
      "billing_mode": "credits",
      "credits": 947,
      "max_users": 0,
      "active_users": null,
      "billing_expires": null,
      "created_at": null
    },
    {
      "id": 100295821,
      "username": "reseller_bob",
      "email": "bob@example.com",
      "member_group_id": 4,
      "member_group_name": "RESELLER",
      "status": 1,
      "billing_mode": "credits",
      "credits": 0.25,
      "max_users": 0,
      "active_users": null,
      "billing_expires": null,
      "created_at": 1578098423
    },
    {
      "id": 100341778,
      "username": "reseller_carol",
      "email": "carol@example.com",
      "member_group_id": 65,
      "member_group_name": "RESELLER MASTER PREMIUM",
      "status": 1,
      "billing_mode": "credits",
      "credits": 2538,
      "max_users": 0,
      "active_users": null,
      "billing_expires": 1783911599,
      "created_at": 1579225251
    }
  ],
  "next_cursor": 100341778
}
```

## Examples

### cURL

```bash
curl -H "Authorization: Bearer <your-api-key>" \
  "https://<your-panel-domain>/panel-api/v1/resellers?limit=3"
```

### PHP SDK

```php
require __DIR__ . '/api-panel-php-sdk-1.0.0/autoload.php';
use XtreamAI\PanelApi\PanelApiClient;

$client = new PanelApiClient(baseUrl: 'https://<your-panel-domain>', token: '<your-api-key>');
$page = $client->resellers->list(limit: 50, status: true);
foreach ($page->items as $reseller) {
    echo $reseller->id, ' ', $reseller->username, PHP_EOL;
}
if ($page->nextCursor !== null) {
    $next = $client->resellers->list(limit: 50, cursor: (string) $page->nextCursor);
}
```

### Python SDK

```python
from xtream_ai_panel_api import PanelApiClient

client = PanelApiClient(base_url="https://<your-panel-domain>", token="<your-api-key>")
page = client.resellers.list(limit=50, status=True)
for reseller in page.items:
    print(reseller.id, reseller.username)
if page.next_cursor is not None:
    next_page = client.resellers.list(limit=50, cursor=str(page.next_cursor))
```

## Errors

| HTTP | Error slug | When it happens | How to fix |
| ---- | ---------- | --------------- | ---------- |
| 401 | `invalid_key` | Missing, malformed, or unknown API key. | Send a live key in `Authorization: Bearer <token>`. |
| 403 | `insufficient_scope` | The key does not carry `resellers:read`. Reseller keys always land here because the scope is admin-only at issuance. | Use an admin key, or (from an integration owned by a reseller) call `GET /me` instead to inspect the caller's own account. |
| 429 | `rate_limited` | The per-key request budget for this minute is spent. | Slow down. The default budget is 300 requests per minute; back off and retry after the minute rolls over. |

## See also

- [Get a single reseller](/docs/?page=xai-ref-resellers-get)
- [Create a reseller](/docs/?page=xai-ref-resellers-create)
- [Panel API Resellers overview](/docs/?page=xai-ref-resellers-list)
