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. The rows do not include owner_id, so the list alone does not tell you which account is the parent of which; the panel shows the tree under Resellers Network.

Endpoint

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

Authentication

Send the API key in the Authorization: Bearer <your-api-key> header. Both key types can call this endpoint, with different reach:

  • Admin key: every reseller on the panel.
  • Reseller key: only the caller's own sub-resellers and their sub-resellers (two levels down), the same accounts the reseller sees under Resellers Network in the panel. The caller itself, its parent, its siblings and any administrator account never appear. See Reseller keys below.

Required scope

  • Admin key: resellers:read
  • Reseller key: subresellers:read

A key of one type does not use the other type's scope: an admin key still needs resellers:read, and a reseller key can never hold 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.

Reseller keys

A reseller key needs two things to read its sub-resellers:

  1. The subresellers:read scope on the key (See sub-resellers in Settings → Panel API Keys). Existing keys keep their scopes: issue a new key with it.
  2. The Can Create Subresellers permission on the reseller's member group, the same permission that shows Resellers Network in the panel. Without it the call returns 403 sub_reseller_view_not_allowed. The check runs on every request, so when the administrator removes the permission the next call is refused.

Every filter (username, member_group_id, status, cursor) works inside that reach only: a username outside the reseller's tree returns an empty items, exactly like a username that does not exist. The rows have the same fields as for an admin key. Reading is all a reseller key can do here: updating a reseller and adjusting its credits stay admin-only.

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.3.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 An admin key without resellers:read, or a reseller key without subresellers:read. details.required_scope names the scope that is missing for that key type. Issue a new key with the scope. From a reseller integration, GET /me still returns the caller's own account without any scope.
403 sub_reseller_view_not_allowed Reseller key only: the reseller's member group does not have Can Create Subresellers enabled. Ask the panel administrator to enable it for the group.
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