Enable a line
If you are starting a new integration instead of migrating an existing one, prefer the native v1 API with the official SDKs. The XC dialect keeps compatibility with legacy tooling; the native dialect gives you typed models, header-based idempotency, and structured HTTP status codes.
action=enable_line flips the reseller-visible enabled flag on a subscriber line to true. The request is translated to the native POST /panel-api/v1/lines/{id}/enable and rewrapped in the classic {"status": "STATUS_SUCCESS", "data": {...}} envelope.
Two flags govern whether a line serves traffic:
enabledis the reseller-visible toggle.enable_lineanddisable_linemove it.admin_enabledis the admin override. If it isfalse, the line stays blocked no matter whatenabledsays. Onlyedit_lineon an admin key can change it.
Enabling a line does not extend its expiry. If the line is already past exp_date, it remains effectively unusable until extend_line or an edit sets a future exp_date.
If the caller is a reseller in users billing mode and the line is not a trial, the endpoint re-checks the slot cap before flipping. Enabling a line that would push the reseller over the slot limit returns STATUS_INSUFFICIENT_CREDITS with slot_limit_exceeded. This is the same guard create_line runs. Reseller in credits mode and admin keys skip this check.
Endpoint
POST https://<your-panel-domain>/panel-api/xc/{accesscode}/admin/index.php?action=enable_line
Both /admin/index.php and /reseller/index.php are accepted. The admin-versus-reseller decision comes from the key.
Authentication
Any one of these three forms:
?api_key=<your-api-key>in the query string.api_key=<your-api-key>in the POST body form field.Authorization: Bearer <your-api-key>HTTP header.
See Authentication.
Required scope
lines:write.
Idempotency
Optional. Pass rid=<unique-per-operation> to opt in. Since enabling is naturally idempotent (twice-enabled stays enabled), the practical benefit is limited to replaying the response payload; the underlying flag is already at target. See the idempotency section.
Request body
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
id |
int | yes | The line to enable. | |
rid |
string | no | Idempotency identifier. |
Response
data is the full Line object with enabled=true. Same shape used by action=get_line.
{
"status": "STATUS_SUCCESS",
"data": {
"id": 172511994,
"username": "u_a1b2c3d4",
"password": "Sup3rSecret1",
"member_id": 100,
"exp_date": 1849365538,
"max_connections": 3,
"is_trial": false,
"is_restreamer": false,
"enabled": true,
"admin_enabled": true,
"bouquets": [2, 4],
"created_at": 1786207138
}
}
HTTP status is always 200, even on failure.
Examples
cURL
curl -X POST "https://<your-panel-domain>/panel-api/xc/panel_api/admin/index.php?api_key=<your-api-key>&action=enable_line" \
-d "id=172511994" \
-d "rid=en-172511994-2026-01-15"
PHP (raw HTTP)
$url = 'https://<your-panel-domain>/panel-api/xc/panel_api/admin/index.php'
. '?' . http_build_query(['api_key' => '<your-api-key>', 'action' => 'enable_line']);
$body = http_build_query([
'id' => 172511994,
'rid' => 'en-172511994-' . bin2hex(random_bytes(8)),
]);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $body,
]);
$resp = json_decode(curl_exec($ch), true);
curl_close($ch);
if (($resp['status'] ?? '') !== 'STATUS_SUCCESS') {
throw new RuntimeException($resp['data']['message'] ?? 'enable_line failed');
}
Python (raw HTTP)
import requests, secrets
r = requests.post(
"https://<your-panel-domain>/panel-api/xc/panel_api/admin/index.php",
params={"api_key": "<your-api-key>", "action": "enable_line"},
data={
"id": 172511994,
"rid": f"en-172511994-{secrets.token_hex(8)}",
},
timeout=30,
)
r.raise_for_status()
body = r.json()
if body.get("status") != "STATUS_SUCCESS":
raise RuntimeError(body["data"].get("message", "enable_line failed"))
Errors
Response is always HTTP 200. Branch on status, then data.error.
| status | Error slug | When it happens | How to fix |
|---|---|---|---|
STATUS_INVALID_DATA |
validation_error |
id is missing or empty. data.details.field is "id". |
Send a numeric id. |
STATUS_FAILURE |
not_found |
The id does not exist, or a reseller key targeted a line owned by another reseller. | Verify the id and ownership. |
STATUS_INSUFFICIENT_CREDITS |
slot_limit_exceeded |
Reseller in users billing mode; enabling this non-trial line would push the reseller over its slot cap. |
Delete unused lines, disable a peer line, or raise the cap. |
STATUS_NO_PERMISSIONS |
insufficient_scope |
The key does not have lines:write. |
Grant the scope. |
STATUS_FAILURE |
idempotency_conflict |
Same rid reused with a different body. |
Pick a new rid. |
STATUS_FAILURE |
idempotency_in_flight |
Same rid is still processing. |
Retry after a moment. |
STATUS_FAILURE |
invalid_key |
Token missing, unknown, disabled, expired, or IP not in allow-list. | Verify the token and the IP allow-list. |
STATUS_FAILURE |
rate_limited |
Per-minute cap or per-IP cap exceeded. | Back off. |
STATUS_FAILURE |
api_disabled |
Panel API is switched off. | Contact the panel admin. |