---
title: "SDK Cheat Sheet"
description: "Every Panel API SDK operation as a one-liner. PHP and Python side by side. Keep this open while you code — no scrolling through resource pages for basic calls."
---

# SDK Cheat Sheet

Every operation the SDK supports, one line of PHP + one line of Python. For the full documentation of each call (parameters, defaults, response fields, error slugs), follow the link on the right. Assumes a client already constructed as:

```php
<?php
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>',
);
```

```python
from xtream_ai_panel_api import PanelApiClient

client = PanelApiClient(
    base_url="https://<your-panel-domain>",
    token="<your-api-key>",
)
```

## Identity

| PHP | Python | What it returns |
|---|---|---|
| `$client->me->get()` | `client.me.get()` | Caller identity (`type`, `scopes`, billing snapshot). See [Get caller identity](/docs/?page=xai-ref-me). |
| `$client->health()` | `client.health()` | Public liveness probe. No auth required. See [Health check](/docs/?page=xai-ref-health). |

## Lines

| PHP | Python | Docs |
|---|---|---|
| `$client->lines->list(limit: 50)` | `client.lines.list(limit=50)` | [List lines](/docs/?page=xai-ref-lines-list) |
| `$client->lines->get(172504295)` | `client.lines.get(172504295)` | [Retrieve line](/docs/?page=xai-ref-lines-get) |
| `$client->lines->create(packageId: 42, memberId: 100)` | `client.lines.create(package_id=42, member_id=100)` | [Create line](/docs/?page=xai-ref-lines-create) |
| `$client->lines->update(172504295, notes: 'renewed')` | `client.lines.update(172504295, notes="renewed")` | [Update line](/docs/?page=xai-ref-lines-update) |
| `$client->lines->enable(172504295)` | `client.lines.enable(172504295)` | [Enable line](/docs/?page=xai-ref-lines-enable) |
| `$client->lines->disable(172504295)` | `client.lines.disable(172504295)` | [Disable line](/docs/?page=xai-ref-lines-disable) |
| `$client->lines->renew(172504295, packageId: 42)` | `client.lines.renew(172504295, package_id=42)` | [Renew line](/docs/?page=xai-ref-lines-renew) |
| `$client->lines->resetPassword(172504295)` | `client.lines.reset_password(172504295)` | [Reset password](/docs/?page=xai-ref-lines-reset-password) |
| `$client->lines->delete(172504295)` | `client.lines.delete(172504295)` | [Delete line](/docs/?page=xai-ref-lines-delete) |
| `$client->lines->connections(172504295)` | `client.lines.connections(172504295)` | [List connections](/docs/?page=xai-ref-lines-connections) |

## Catalog

| PHP | Python | Docs |
|---|---|---|
| `$client->catalog->packages()` | `client.catalog.packages()` | [List packages](/docs/?page=xai-ref-catalog-packages) |
| `$client->catalog->bouquets()` | `client.catalog.bouquets()` | [List bouquets](/docs/?page=xai-ref-catalog-bouquets) |
| `$client->catalog->streams(limit: 100)` | `client.catalog.streams(limit=100)` | [List live streams](/docs/?page=xai-ref-catalog-streams) |
| `$client->catalog->stream(482)` | `client.catalog.stream(482)` | [Retrieve stream](/docs/?page=xai-ref-catalog-stream) |
| `$client->catalog->vods(search: 'inception')` | `client.catalog.vods(search="inception")` | [List VODs](/docs/?page=xai-ref-catalog-vods) |
| `$client->catalog->vod(9042)` | `client.catalog.vod(9042)` | [Retrieve VOD](/docs/?page=xai-ref-catalog-vod) |

## Resellers

Admin-only for most operations. A reseller with `subresellers:write` can create sub-resellers under itself.

| PHP | Python | Docs |
|---|---|---|
| `$client->resellers->list()` | `client.resellers.list()` | [List resellers](/docs/?page=xai-ref-resellers-list) |
| `$client->resellers->get(260595)` | `client.resellers.get(260595)` | [Retrieve reseller](/docs/?page=xai-ref-resellers-get) |
| `$client->resellers->create(username: 'newco', memberGroupId: 3)` | `client.resellers.create(username="newco", member_group_id=3)` | [Create reseller](/docs/?page=xai-ref-resellers-create) |
| `$client->resellers->update(260595, notes: '...')` | `client.resellers.update(260595, notes="...")` | [Update reseller](/docs/?page=xai-ref-resellers-update) |
| `$client->resellers->billing(260595)` | `client.resellers.billing(260595)` | [Read billing](/docs/?page=xai-ref-resellers-billing) |
| `$client->resellers->adjustBilling(260595, delta: 100)` | `client.resellers.adjust_billing(260595, delta=100)` | [Adjust billing](/docs/?page=xai-ref-resellers-billing-adjust) |

## Pagination

Every `list()` returns a `PaginatedResponse` with `items` and an opaque `nextCursor` (`next_cursor`). The SDK does not loop for you — pass the cursor back to fetch the next page.

```php
<?php
$page = $client->lines->list(limit: 50);
while (true) {
    foreach ($page->items as $line) { /* ... */ }
    if ($page->nextCursor === null) break;
    $page = $client->lines->list(limit: 50, cursor: $page->nextCursor);
}
```

```python
page = client.lines.list(limit=50)
while True:
    for line in page.items:
        pass  # ...
    if page.next_cursor is None:
        break
    page = client.lines.list(limit=50, cursor=page.next_cursor)
```

Full walk-through in [SDKs Overview → Pagination](/docs/?page=panel-api-sdks#pagination).

## Idempotency

Every write auto-generates a UUID. Override with a stable business key when the caller is retriable (webhooks, job queues, cron):

```php
<?php
$client->lines->create(
    packageId: 42, memberId: 100, username: 'johndoe',
    idempotencyKey: 'invoice-INV-42',
);
```

```python
client.lines.create(
    package_id=42, member_id=100, username="johndoe",
    idempotency_key="invoice-INV-42",
)
```

Full contract in [Retry and Idempotency with the SDK](/docs/?page=panel-api-sdk-retry-idempotency).

## Error handling

Catch specific first, base class last. Every exception has `.slug`, `.request_id`, `.status_code`, `.details`.

```php
<?php
use XtreamAI\PanelApi\Exceptions\{
    InsufficientCreditsException, ValidationException, PanelApiException,
};

try {
    $client->lines->create(packageId: 42, memberId: 100);
} catch (InsufficientCreditsException $e) {
    // Reseller is broke.
} catch (ValidationException $e) {
    error_log("bad field: " . $e->field());
} catch (PanelApiException $e) {
    error_log("api error req={$e->requestId} slug={$e->slug}");
}
```

```python
from xtream_ai_panel_api.exceptions import (
    InsufficientCreditsException, ValidationException, PanelApiException,
)

try:
    client.lines.create(package_id=42, member_id=100)
except InsufficientCreditsException:
    pass  # Reseller is broke.
except ValidationException as e:
    print("bad field:", e.field)
except PanelApiException as e:
    print(f"api error req={e.request_id} slug={e.slug}")
```

Full exception hierarchy in [Errors with the SDK](/docs/?page=panel-api-sdk-errors).

## Common one-shot flows

### Provision a new customer after payment

```php
<?php
$line = $client->lines->create(
    packageId:      42,
    memberId:       100,
    email:          'johndoe@example.com',
    idempotencyKey: 'payment-'.$paymentId,
);
echo "Deliver credentials: {$line->username} / {$line->password}", PHP_EOL;
```

```python
line = client.lines.create(
    package_id=42, member_id=100, email="johndoe@example.com",
    idempotency_key=f"payment-{payment_id}",
)
print(f"Deliver credentials: {line.username} / {line.password}")
```

### Renew a subscription

```php
<?php
$line = $client->lines->renew(
    $lineId,
    packageId: 42,
    idempotencyKey: 'renewal-'.$invoiceId,
);
echo "New expiry: {$line->expDate}", PHP_EOL;
```

```python
line = client.lines.renew(
    line_id, package_id=42,
    idempotency_key=f"renewal-{invoice_id}",
)
print(f"New expiry: {line.exp_date}")
```

### Suspend a delinquent account

```php
<?php
$client->lines->disable($lineId, idempotencyKey: 'suspend-'.$lineId);
```

```python
client.lines.disable(line_id, idempotency_key=f"suspend-{line_id}")
```

### Rotate a compromised customer password

```php
<?php
$newPassword = $client->lines->resetPassword($lineId);
notifyCustomer($newPassword);
```

```python
new_password = client.lines.reset_password(line_id)
notify_customer(new_password)
```

### Reconcile: is this line still active on the panel?

```php
<?php
try {
    $line = $client->lines->get($lineId);
    $active = $line->enabled && !$line->isExpired;
} catch (\XtreamAI\PanelApi\Exceptions\NotFoundException) {
    $active = false;
}
```

```python
from xtream_ai_panel_api.exceptions import NotFoundException

try:
    line = client.lines.get(line_id)
    active = line.enabled and not line.is_expired
except NotFoundException:
    active = False
```

## Constants worth memorizing

- **Default timeout**: 30 s per request.
- **Default retries**: 3 attempts on top of the original.
- **Max `limit`** on any list endpoint: 100 (some default 50).
- **Idempotency window** on the server: at least 24 hours.
- **429 Retry-After cap** honored by the SDK: 60 s.

## See also

- [SDKs Overview](/docs/?page=panel-api-sdks). The full picture: what you get vs raw HTTP.
- [Common Tasks](/docs/?page=panel-api-migration-recipes). Longer worked recipes with the full context.
- [Working with Lines](/docs/?page=panel-api-lines) · [Working with Catalog](/docs/?page=panel-api-catalog) · [Working with Resellers](/docs/?page=panel-api-resellers). Resource-level guides.
