List packages
Returns every package the calling key can use when creating a line. Packages are the price sheet of the panel: each row carries a set of official_* fields describing the paid subscription (credit cost, duration, max connections) and an optional set of trial_* fields describing the trial variant of the same package.
The endpoint is scoped silently by caller type. An admin key sees every package in the panel. A reseller key sees only the packages whose groups list contains the reseller's member_group_id (in other words, the packages the admin has authorized their group to sell). No error is raised when the visible set is empty; the response is {"items": []}.
Endpoint
GET https://<your-panel-domain>/panel-api/v1/packages
Authentication
Bearer token in the Authorization header. See Authentication for how to mint and rotate keys.
Required scope
packages:read.
Query parameters
This endpoint takes no query parameters. Packages are ordered alphabetically by package_name and the full list is returned in one call. There are typically fewer than a few hundred packages per panel, so pagination is not applied.
Response
The response wraps the list in an items array. Each item has the following fields.
| Field | Type | Description |
|---|---|---|
id |
int | Numeric package id. Stable across the panel's lifetime. |
package_name |
string | Human readable name shown in the panel UI. |
is_trial |
bool | true when the package can only be sold as a trial. Paid fields will be zero. |
is_official |
bool | false marks the package as internal or hidden from public storefronts. |
official_credits |
float | Credits charged when the package is sold as a paid subscription. |
official_duration |
int | Length of the paid subscription in official_duration_in units. |
official_duration_in |
string | One of hours, days, weeks, months, years. |
trial_credits |
float | Credits charged when the caller requests a trial. 0 if trials are disabled. |
trial_duration |
int | Length of the trial in trial_duration_in units. 0 if trials are disabled. |
trial_duration_in |
string | Same allowed values as official_duration_in. |
max_connections |
int | Maximum concurrent devices a subscriber on this package can have logged in. |
is_restreamer |
bool | true when the package enables restreamer permissions. |
forced_country |
string | Two letter ISO country code that forces every line created under this package to that country. Empty string means no restriction. |
Example response.
{
"items": [
{
"id": 76,
"package_name": "Package 12M Adult 1 Connection",
"is_trial": false,
"is_official": true,
"official_credits": 12,
"official_duration": 12,
"official_duration_in": "months",
"trial_credits": 0,
"trial_duration": 0,
"trial_duration_in": "hours",
"max_connections": 1,
"is_restreamer": false,
"forced_country": ""
},
{
"id": 67,
"package_name": "Package 1M Adult 1 Connection",
"is_trial": false,
"is_official": true,
"official_credits": 1,
"official_duration": 1,
"official_duration_in": "months",
"trial_credits": 0,
"trial_duration": 0,
"trial_duration_in": "hours",
"max_connections": 1,
"is_restreamer": false,
"forced_country": ""
},
{
"id": 69,
"package_name": "Package 3M Adult 1 Connection",
"is_trial": false,
"is_official": true,
"official_credits": 3,
"official_duration": 3,
"official_duration_in": "months",
"trial_credits": 0,
"trial_duration": 0,
"trial_duration_in": "hours",
"max_connections": 1,
"is_restreamer": false,
"forced_country": ""
}
]
}
Examples
cURL
curl -H "Authorization: Bearer <your-api-key>" \
https://<your-panel-domain>/panel-api/v1/packages
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>');
$packages = $client->catalog->packages();
foreach ($packages as $p) {
echo $p->id, ' ', $p->packageName, ' (', $p->officialCredits, " credits)\n";
}
Python SDK
from xtream_ai_panel_api import PanelApiClient
client = PanelApiClient(base_url="https://<your-panel-domain>", token="<your-api-key>")
packages = client.catalog.packages()
for p in packages:
print(p.id, p.package_name, p.official_credits)
Errors
| HTTP | Error slug | When it happens | How to fix |
|---|---|---|---|
| 401 | invalid_key |
The Authorization header is missing, malformed, or names a key that does not exist. |
Check the header. See Authentication. |
| 403 | insufficient_scope |
The key does not carry packages:read. |
Regenerate the key with packages:read in its scope list, or use a key that has it. |
| 429 | rate_limited |
The per key rate limit has been exceeded. Response carries Retry-After: 60 and X-RateLimit-* headers. |
Back off for the number of seconds in Retry-After and retry. |