Get live connections for a line
GET /lines/{id}/connections lists the streaming sessions currently open on a subscriber line. It is what support pages call to answer "who is watching what on this account right now, and from where". It is also the endpoint that dashboards poll to render live-viewer counts.
Each item in the response represents one live client (a device or app currently pulling a stream). The list is capped at 200 items ordered by most-recent first, and each item carries the client's IP, country (as inferred by the panel's GeoIP database), the elapsed time since the session opened, and, when the panel can resolve it, the id and name of the content being streamed. Sessions to live channels are labeled content_type: "live"; sessions to VOD movies or series episodes are labeled content_type: "movie" with a nested is_serie flag distinguishing the two.
Tenant isolation matches the rest of /lines: a reseller key can only inspect connections for lines it owns, and a request for another reseller's line returns 404 not_found (the same slug used when the id does not exist at all).
Endpoint
GET https://<your-panel-domain>/panel-api/v1/lines/{id}/connections
Authentication
Bearer token in the Authorization header. See Authentication.
Required scope
lines:read.
Path parameters
| Name | Type | Description |
|---|---|---|
id |
int | The line's panel-wide numeric id. Non-numeric values are treated as 0 and return 404 not_found. |
Response
An object with a single field:
| Field | Type | Description |
|---|---|---|
items |
Connection[] | Live sessions currently open on the line. Up to 200 items, ordered by started_at descending. Empty array when no session is open. |
Each Connection item:
| Field | Type | Description |
|---|---|---|
connection_id |
int | Panel-internal id of the live-client session. Stable while the session is open. Not meant to be persisted across sessions. |
content_type |
string | Either "live" (channel) or "movie" (VOD or series episode). For series episodes, is_serie is true. |
content_id |
int or null | Id of the channel or VOD row, when the panel can resolve it. null for sessions on channels or VODs the panel cannot cross-reference (typically deleted content that a client is still holding open). |
content_name |
string | Human-readable name of the content, or "" when the panel cannot resolve it. |
started_at |
int | UTC Unix epoch when the session opened. |
elapsed_sec |
int | Seconds elapsed between started_at and the moment the panel served the request. |
client_ip |
string | The IP the client is streaming from, as observed by the panel edge. |
client_country |
string | ISO 3166-1 alpha-2 country code inferred from client_ip. Empty string if the panel's GeoIP database has no answer. |
is_serie |
bool | Present only when content_type == "movie". true for a series episode, false for a stand-alone VOD. |
Empty result (line exists, nobody watching):
{
"items": []
}
Populated result (an active line with many concurrent sessions):
{
"items": [
{
"connection_id": 100000042,
"content_type": "live",
"content_id": 5721,
"content_name": "Package 7 HD",
"started_at": 1783791431,
"elapsed_sec": 2415124,
"client_ip": "203.0.113.14",
"client_country": "FR"
},
{
"connection_id": 100000041,
"content_type": "movie",
"content_id": 8834,
"content_name": "Movie 42",
"started_at": 1783791429,
"elapsed_sec": 2415126,
"client_ip": "203.0.113.87",
"client_country": "NL",
"is_serie": false
},
{
"connection_id": 100000040,
"content_type": "movie",
"content_id": 12907,
"content_name": "Show 3 S01E04",
"started_at": 1783791429,
"elapsed_sec": 2415126,
"client_ip": "203.0.113.140",
"client_country": "IR",
"is_serie": true
}
]
}
The 200-item cap means a very active line can have live sessions the endpoint does not return. This is a hard cap in the query, not a paginated page. If you need to audit every session for a reseller with thousands of concurrent connections, iterate the lines first with
GET /linesand call this endpoint per line.
elapsed_secis computed server-side using the current time on the panel, not the caller's clock. It is safe to display without any clock-skew correction.
Examples
cURL
curl -X GET "https://<your-panel-domain>/panel-api/v1/lines/1512227/connections" \
-H "Authorization: Bearer <your-api-key>"
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>');
$sessions = $client->lines->connections(1512227);
echo count($sessions) . " active session(s)\n";
foreach ($sessions as $s) {
echo sprintf(" %s from %s watching %s\n",
$s->clientIp, $s->clientCountry, $s->contentName ?: '(unresolved)');
}
Python SDK
from xtream_ai_panel_api import PanelApiClient
client = PanelApiClient(base_url="https://<your-panel-domain>", token="<your-api-key>")
sessions = client.lines.connections(1512227)
print(f"{len(sessions)} active session(s)")
for s in sessions:
print(f" {s.client_ip} from {s.client_country} watching {s.content_name or '(unresolved)'}")
Errors
| HTTP | Error slug | When it happens | How to fix |
|---|---|---|---|
| 401 | invalid_key |
The Authorization header is missing, malformed, points to an unknown key, or the key is disabled, expired, deleted, or IP-restricted. |
Verify the token. Reissue if it was rotated. |
| 403 | insufficient_scope |
The key does not have lines:read. |
Grant lines:read from the panel or issue a new key with that scope. |
| 404 | not_found |
The id does not exist, or a reseller key is asking for a line owned by a different reseller. Both cases return the same body, so no tenant discovery is possible. | Confirm the id and, if you are using a reseller key, that the line's member_id matches your own reg_user_id. |
| 429 | rate_limited |
You exceeded the key's per-minute rate limit or the panel-wide per-IP limit. | Honor the Retry-After header and lower the polling frequency (this is a live snapshot; polling more often than once every few seconds rarely helps). |
| 503 | api_disabled |
An admin has turned the Panel API off for this panel. | Contact the panel admin. |