Renew a line

Push a line's exp_date forward by the official duration of a package. The new expiry is max(current_exp_date, now) + package.official_duration. If the line already expired, the countdown restarts from now. If it is still active, the extension is added on top of the current expiry so no days are lost.

Renewing also reactivates the line: admin_enabled and enabled are both set to true in the same statement. That way a renew brings back a previously disabled or admin-blocked line without a second call.

Billing behavior:

  • Reseller in credits mode deducts package.official_credits before the update. Failure to deduct returns 402 insufficient_credits. If the update fails after the deduction, the credits are refunded.
  • Reseller in users mode renews for free (a slot is already accounted for as long as the line exists).
  • Admin keys skip the billing checks entirely.

Perpetual lines (exp_date == null) cannot be renewed. Renewing would set an expiry and effectively degrade the line, so the endpoint returns 422 line_has_no_expiry. Use update with a chosen exp_date if you really want to convert a perpetual line into a timed one.

Endpoint

POST https://<your-panel-domain>/panel-api/v1/lines/{id}/renew

Authentication

Bearer token in the Authorization header. See Panel API authentication.

Required scope

lines:write.

Idempotency

Required. Renewals are the classic double-charge risk: sending the same Idempotency-Key on a retry returns the original response instead of charging twice. A missing header returns 400 missing_idempotency_key.

Path parameters

Name Type Description
id int The line id to renew.

Request body

Field Type Required Default Description
package_id int yes Package to renew with. Must exist, must not be a trial package. Reseller keys must have access to the package.
{
  "package_id": 42
}

Response

200 OK with the full line object. exp_date reflects the new expiry, and enabled and admin_enabled are both true.

{
  "id": 172504295,
  "username": "u_a1b2c3d4",
  "password": "c30b22e4",
  "member_id": 100,
  "exp_date": 1791477054,
  "max_connections": 1,
  "is_trial": false,
  "is_restreamer": false,
  "enabled": true,
  "admin_enabled": true,
  "bouquets": [],
  "created_at": 1786206654
}

Examples

cURL

curl -X POST https://<your-panel-domain>/panel-api/v1/lines/172504295/renew \
  -H "Authorization: Bearer <your-api-key>" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: invoice-INV-2026-00915" \
  -d '{"package_id": 42}'

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>');
$line = $client->lines->renew(
    id:             172504295,
    packageId:      42,
    idempotencyKey: 'invoice-INV-2026-00915',
);
echo 'new expiry ', $line->expDate?->format(DATE_ATOM), PHP_EOL;

Python SDK

from xtream_ai_panel_api import PanelApiClient

client = PanelApiClient(base_url="https://<your-panel-domain>", token="<your-api-key>")
line = client.lines.renew(
    id=172504295,
    package_id=42,
    idempotency_key="invoice-INV-2026-00915",
)
print("new expiry", line.exp_date.isoformat() if line.exp_date else None)

Errors

HTTP Error slug When it happens How to fix
400 missing_idempotency_key The Idempotency-Key header was not sent. Send a per-intent key on every write.
401 invalid_key Token is unknown, expired, disabled, or deleted. Check the token or issue a new one.
402 billing_expired Reseller subscription has expired. Extend the reseller subscription.
402 insufficient_credits Reseller (credits mode) lacks credits for the package. Top up credits, or pick a cheaper package.
403 package_not_accessible Reseller cannot sell from that package. Use a package inside the reseller's member group.
403 insufficient_scope Token lacks lines:write. Issue a key with the scope.
404 not_found The line id does not exist, or a reseller key targeted a line it does not own. Verify the id and ownership.
409 idempotency_conflict Same key was reused with a different body. Use a fresh key.
409 idempotency_in_flight Same key is still processing. Retry after a moment.
422 validation_error Missing package_id, or the package id does not exist. See details.field in the response.
422 renew_with_trial_package_not_allowed package_id points to a trial package. Pick a non-trial package.
422 line_has_no_expiry The line is perpetual (exp_date == null) and renewing would set an expiry. Use update with an explicit exp_date instead.
429 rate_limited The key hit its per-minute cap. Back off and retry after Retry-After seconds.

See also