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.

{
  "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

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

PHP SDK

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

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