Renew a line, POST /ext/line/{uuid}/renew
If you are starting a new integration instead of migrating, prefer the native v1 API with the official SDKs. The OneStream dialect exists to let existing OneStream code point at Xtream AI with only a base URL change.
Push a line's expiry forward by the official duration of a package. The new expiry is max(current_expire_at, now) + package.official_duration. An already expired line restarts from now, an active line accumulates the extension on top of its current expiry so no days are lost.
Renewing also reactivates the line: it comes back enabled even if it had been disabled. That way one call to renew is enough to bring a paying customer back after a lapse.
Billing behavior mirrors the create endpoint: reseller keys in credits mode pay the package's official credits, users-mode resellers renew for free (the slot is already accounted for), and admin keys skip billing checks entirely.
Endpoint
POST https://<your-panel-domain>/panel-api/onestream/ext/line/{uuid}/renew
Authentication
X-Api-Key. X-Auth-User and Authorization: Bearer also accepted. See Authentication.
Required scope
lines:write.
Idempotency
Optional but strongly recommended. Renewals are the classic double-charge risk: send a unique rid in the JSON body so a retry after a timeout returns the cached response instead of charging twice. If your billing system did not see the response, use GET /ext/transaction/{rid} to look up the outcome before retrying.
Path parameters
| Name | Type | Description |
|---|---|---|
uuid |
string | The opaque line UUID returned by /ext/line/create, /ext/lines, or /ext/line/find. |
Request body
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
package (or package_id) |
int | no | line's current package | Package to renew with. Must exist. Reseller keys must have access. If omitted the caller's current package cost is not automatically re-applied, so most integrations pass it explicitly. |
rid |
string | no | Idempotency key. See above. |
{
"package": 42,
"rid": "renew-user-42-2026-08"
}
Response
200 OK with the same compact shape as create: the opaque line_id, the new expire_at as an ISO 8601 UTC string, the transaction_amount debited, and the echoed rid.
{
"line_id": "b32c1a04-11ea-4c67-8fd1-0001000000f1",
"expire_at": "2026-10-08T00:00:00+00:00",
"transaction_amount": 0,
"rid": "renew-user-42-2026-08"
}
Examples
cURL
curl -X POST "https://<your-panel-domain>/panel-api/onestream/ext/line/b32c1a04-11ea-4c67-8fd1-0001000000f1/renew" \
-H "X-Api-Key: <your-api-key>" \
-H "Content-Type: application/json" \
-d '{
"package": 42,
"rid": "renew-user-42-2026-08"
}'
PHP raw
$uuid = 'b32c1a04-11ea-4c67-8fd1-0001000000f1';
$ch = curl_init("https://<your-panel-domain>/panel-api/onestream/ext/line/{$uuid}/renew");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'X-Api-Key: <your-api-key>',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'package' => 42,
'rid' => 'renew-user-42-2026-08',
]),
]);
$body = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
Python raw
import requests
uuid_ = "b32c1a04-11ea-4c67-8fd1-0001000000f1"
r = requests.post(
f"https://<your-panel-domain>/panel-api/onestream/ext/line/{uuid_}/renew",
headers={"X-Api-Key": "<your-api-key>"},
json={"package": 42, "rid": "renew-user-42-2026-08"},
timeout=30,
)
r.raise_for_status()
print(r.json())
Errors
| HTTP | Error slug (or message) | When it happens | How to fix |
|---|---|---|---|
| 401 | Invalid API key |
Token is unknown, expired, disabled, or deleted. | Check the token or issue a new one. |
| 402 | Insufficient credits balance |
Reseller in credits mode lacks credits for the package. | Top up credits, or pick a cheaper package. |
| 403 | insufficient_scope |
Token lacks lines:write. |
Issue a key with the scope. |
| 403 | package_not_accessible |
Reseller cannot sell from that package. | Use a package inside the reseller's member group. |
| 409 | Transaction already processed |
Same rid was reused with a different body. |
Use a fresh rid, or replay with the exact original body. |
| 422 | line_id not found or invalid |
The UUID in the URL is malformed, was not issued by this panel, or belongs to a different panel. This response is uniform on purpose so it cannot be used as an enumeration oracle. | Verify the UUID you stored on line-creation. |
| 422 | validation_error |
Unknown package, trial package used for renew, missing required field in the underlying handler. |
See details.field in the response. |
| 429 | Rate limit exceeded |
The key hit its per-minute cap. | Back off and retry after Retry-After seconds. |
| 501 | not_implemented |
A GET request was sent to this URL. |
Only POST is accepted. This blocks browser prefetch and misbehaving retry loops from renewing lines by walking URLs. |