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:
- The
subresellers:readscope on the key (See sub-resellers in Settings → Panel API Keys). Existing keys keep their scopes: issue a new key with it. - 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. |