---
title: "For Resellers"
description: "What a reseller can and cannot do with the Panel API. Getting a key, the endpoint whitelist, what admin controls gate your access, and how sub-resellers work when your admin lets you create them."
---

# For Resellers

The Panel API is the same for admins and resellers — same base URL, same JSON shapes, same errors. What changes is **which endpoints you can reach** and **what data those endpoints see**. This page is the map: what your reseller key can do end to end, what it cannot, and where each restriction comes from.

If you are the panel admin, the [Overview](/docs/?page=panel-api-overview) is a better starting point — it walks the API from the admin's angle. This page assumes you own a reseller account and want to build something against your slice of the panel.

## Getting a key

Your admin has to opt your member group in before you can issue API keys. This is off by default. Ask them to enable **Reseller settings → Member groups → Can create API keys** for your group. Once enabled:

1. Log into your reseller area on the panel.
2. Open **Settings → Panel API Keys**.
3. Click **New key**, name it (for your own bookkeeping — the panel does not use the name), pick the scopes it needs, and optionally restrict it to specific source IPs.
4. Copy the token — it is shown once. Store it in a secret manager, an environment variable, or your billing system's credential vault. Not in code.

The token is a long random string prefixed with something like `pk_live_`. That prefix is the only part safe to log; the rest is the secret. Full token contract lives in [Authentication](/docs/?page=panel-api-authentication).

Reseller keys carry two extra restrictions the admin cannot override:

- They **cannot** include the admin-only scopes (`resellers:read`, `resellers:write`). The panel refuses to attach them at issuance.
- They are tied to your reseller account. If your account gets banned, disabled, or your member group is banned, every call from your key comes back `401 caller_disabled`. Admin keys are not tied to any reg_user and are immune to that.

## What you can do

Everything in the table below is reachable with the standard reseller scope set. The scope column names the exact scope required — the key you issue must carry it or the panel returns `403 insufficient_scope`.

### Lines (your own customers)

You see and manage only lines you created. Lines owned by other resellers are invisible to you — they don't appear in `GET /lines`, and directly fetching `GET /lines/{id}` for an unowned line returns `404`.

| Endpoint | Scope | What you can do |
|---|---|---|
| [List lines](/docs/?page=xai-ref-lines-list) | `lines:read` | Paginate your lines. Filter by username, package, expiry. |
| [Create line](/docs/?page=xai-ref-lines-create) | `lines:write` | Provision a new customer against one of your packages. Consumes credits (credits mode) or a user slot (users mode). |
| [Retrieve line](/docs/?page=xai-ref-lines-get) | `lines:read` | Full record for one of your lines. |
| [Update line](/docs/?page=xai-ref-lines-update) | `lines:write` | Partial update: notes, package, bouquets, expiry, contact info. |
| [Enable / disable](/docs/?page=xai-ref-lines-enable) | `lines:write` | Suspend or reactivate a line without deleting it. Free — no billing side effects. |
| [Renew](/docs/?page=xai-ref-lines-renew) | `lines:write` | Extend a line's expiry by the package's cycle. Consumes credits (credits mode) or is free (users mode). |
| [Reset password](/docs/?page=xai-ref-lines-reset-password) | `lines:write` | Rotate a customer's password after a compromise. |
| [Delete line](/docs/?page=xai-ref-lines-delete) | `lines:write` | Permanent — frees the user slot (users mode) but does not refund credits. |
| [List connections](/docs/?page=xai-ref-lines-connections) | `lines:read` | See who is streaming right now on that line. Useful for suspending abusers. |

### Catalog (what you can sell)

Read-only. You see only the packages and bouquets your admin has assigned to you.

| Endpoint | Scope | Notes |
|---|---|---|
| [List packages](/docs/?page=xai-ref-catalog-packages) | `packages:read` | Every package the admin made available to your group. |
| [List bouquets](/docs/?page=xai-ref-catalog-bouquets) | `bouquets:read` | Every bouquet you can assign to a line. |
| [List / get streams](/docs/?page=xai-ref-catalog-streams) | `streams:read` | Live channel catalogue. |
| [List / get VODs](/docs/?page=xai-ref-catalog-vods) | `vods:read` | Movie catalogue. |

If a package you expect to see is missing, that is an admin config issue — the API just reflects what your member group is allowed to sell.

### Yourself

One endpoint returns your identity. Includes your billing snapshot (mode, balance, user cap), which is the recommended way to check credits before a bulk of writes.

| Endpoint | Scope | Notes |
|---|---|---|
| [Get caller identity](/docs/?page=xai-ref-me) | none | Type (`reseller`), member group, scope list, key prefix, billing snapshot. |

### Sub-resellers (opt-in)

If — and only if — your admin has enabled sub-reseller creation for your member group AND your key was issued with `subresellers:write`, you can create sub-resellers underneath yourself. This is a single endpoint:

| Endpoint | Scope | Notes |
|---|---|---|
| [Create reseller](/docs/?page=xai-ref-resellers-create) | `subresellers:write` | Creates a reseller in one of the sub-reseller member groups the admin exposed to you. The new reseller is your child in the ownership tree. |

You cannot list, read, update or manage billing of your sub-resellers via the API v1 — those flows live in the panel UI today (**Users** section). See [What you cannot do](#what-you-cannot-do) below.

## What you cannot do

The following endpoints exist but require admin-only scopes. Attempting them with a reseller key returns `403 insufficient_scope`.

| Endpoint | Why admin-only |
|---|---|
| [List resellers](/docs/?page=xai-ref-resellers-list) | Requires `resellers:read`. Would expose peers and other admin's customers. |
| [Retrieve reseller](/docs/?page=xai-ref-resellers-get) | Same as above. |
| [Update reseller](/docs/?page=xai-ref-resellers-update) | Requires `resellers:write`. Can change scopes, group, quotas — trust-boundary crossing. |
| [Read billing](/docs/?page=xai-ref-resellers-billing) | Requires `resellers:read`. Your OWN billing is exposed via `GET /me`. |
| [Adjust billing](/docs/?page=xai-ref-resellers-billing-adjust) | Requires `resellers:write`. Credit adjustments for sub-resellers happen in the panel UI in v1. |

If your workflow genuinely needs to manage a sub-reseller's credits programmatically and the panel UI is not enough, talk to your admin — they can call `POST /resellers/{sub_id}/billing/adjust` from an admin key on your behalf.

## Ownership: what your key sees

Every read endpoint returns only rows you are allowed to see. This is enforced at the panel side, not client-side — you cannot bypass it by omitting a filter or crafting a URL.

- `GET /lines` returns your lines. Owned-by filter is baked in.
- `GET /lines/{id}` returns `404` for a line owned by anyone else (even if the numeric ID is valid). The `404` is deliberate — the panel does not tell you "that line exists but is not yours". Same-shaped error whether it was never created, was deleted, or belongs to a peer.
- Catalogue endpoints return what your member group is allowed to see. Two resellers on different groups can get different catalogues from the same call.
- Sub-reseller resources are visible to their creator (via the panel UI), but the API v1 does not currently expose them.

## Billing modes

Your reseller account is in one of two billing modes: **credits** or **users**. Which one applies is set by your admin on your member group. Both are visible in `GET /me`.

### Credits mode

You consume credits when you `POST /lines` (creating a line) and when you `POST /lines/{id}/renew` (renewing). The credit cost per operation is defined per package — see `official_credits` in the package payload from `GET /packages`.

- If your balance is insufficient, the write returns `402 insufficient_credits` (mapped to `InsufficientCreditsException` in the SDK).
- Deleting or disabling a line does NOT refund credits.
- Enabling a disabled line is free — the credit was already spent when the line was created.
- Only the admin can top up your credits. `POST /resellers/{id}/billing/adjust` is admin-only.

### Users mode

You have a hard cap on the number of active users. Each `POST /lines` uses one slot. Deleting a line frees the slot immediately; disabling does NOT — a disabled line still counts against the cap.

- If your cap is full, the write returns `422 insufficient_slots` (mapped in the SDK to the same `InsufficientCreditsException`, so a single catch handles both modes).
- Renewals are free in users mode — the slot is already counted for as long as the line exists.
- Only the admin can raise your cap.

Both flavors return the same exception class in the SDK, so one catch handles both. See [Errors with the SDK](/docs/?page=panel-api-sdk-errors) for the details.

## Rate limits

Reseller keys share the same per-key rate limit contract as admin keys — a burst budget per minute, refilled linearly. Hitting the limit returns `429 rate_limited` with a `Retry-After` header. The SDK honors it automatically up to a 60-second cap.

The exact numbers are set per member group by your admin. `GET /me` includes the effective limit for the caller. If your integration bumps into it regularly, the fix is usually to batch (fetch pages of 100 instead of 10) or to serialize concurrent bursts, not to ask for a limit bump — sustained high volume usually means the caller is doing something that should be a bulk operation, not many singletons.

## Scope selection: less is more

Every key you issue should carry the minimum scopes it actually needs. That "billing-system-only" key that just creates lines does not need `streams:read` or `vods:read`. Fewer scopes means:

- The blast radius of a leaked key is smaller.
- The panel-side rate limit is not shared across purposes — one integration hitting its limit does not stall the other.
- Rotating one key does not break every integration you own.

For a WHMCS-style billing integration, a typical minimal scope set is:

```
lines:write, lines:read, packages:read, bouquets:read
```

For a reseller portal that also lets end users pick between packages:

```
lines:read, lines:write, packages:read, bouquets:read, streams:read, vods:read
```

For sub-reseller provisioning:

```
Add subresellers:write to whichever key does the provisioning.
```

## See also

- [Authentication](/docs/?page=panel-api-authentication). Full auth contract including scopes, IP allow-lists, and rotation.
- [Quickstart](/docs/?page=panel-api-quickstart). Get your first line created in five minutes.
- [SDKs Overview](/docs/?page=panel-api-sdks). The official PHP and Python SDKs give you typed models, typed exceptions, and automatic retry.
- [Common Tasks](/docs/?page=panel-api-migration-recipes). Cookbook recipes — payment-triggered provisioning, renewal after invoice, month-end reconciliation.
- [Get caller identity](/docs/?page=xai-ref-me). One endpoint that answers "what am I, what can I do, and how much do I have left".
