# Resellers

Two pages live under Resellers:

| Page | Purpose |
|---|---|
| Resellers list | All accounts flagged `is_reseller=true`, plus quota usage (sub-accounts created vs allowed) |
| Reseller ACL plans | Permission templates that govern what a reseller can do (CRUD on each feature) |

A reseller may be assigned an ACL plan; without one it is unrestricted. Enforcement is server-side: a request from a reseller session to a capability its plan withholds is refused with `403 PERMISSION_DENIED`, and the body names the permission. This covers the sub-account management endpoints and the reseller's own client-panel surface (DNS, SSL, PHP, databases, email with the mailboxes' spam lists, FTP, files, cron, backups, logs, metrics, phpMyAdmin and webmail single sign-on, and logging in as a sub-account). A narrow permission never overrides a broad one — phpMyAdmin access also requires database management. The reseller's panel reads the plan's flags with its profile and does not offer what the plan withholds: the menu entry of a withheld surface is left out, the **Remote** tab of Backups and the sub-account firewall switch follow `backup_remote` and `modsecurity_manage`, and the API Access page states the refusal without asking. Naming a plan and setting the limits directly are the same permission: with **account plan change** withheld, a reseller can change neither `plan_id` nor a sub-account's package limits.

**Shell Access** governs whether the reseller may give a sub-account an interactive login shell (see § 3). **ModSecurity** governs the firewall switch on the reseller's sub-account page. **API Access** governs whether the reseller may mint and use its own API keys on the client API (see § API Access → Reseller keys); with it withheld, minting and every request signed with an existing reseller key are refused.

**Login to Client Panel** (the SSO control on the Resellers list) opens the reseller's own client panel in a new tab, acting as that reseller: the sub-account pages there work even though the operator's own session cookie stays in the browser.

The client panel does not yet read the ACL, so a reseller sees a refused section as empty rather than as "not permitted".

Suspended sub-accounts still count toward a reseller's sub-account quota; only termination frees a slot. An ACL plan a reseller still uses cannot be deleted (`409 PLAN_IN_USE`, with the reseller count); the three system plans can be edited but never deleted; a new plan whose name resolves to an existing plan id is refused with `409 PLAN_EXISTS`.

**Endpoints used:** `GET /accounts?is_reseller=true`, `GET /resellers/acl-plans`, `POST /resellers/acl-plans`, `PUT /resellers/acl-plans/{id}`, `DELETE /resellers/acl-plans/{id}`, `PUT /accounts/{u}` (reseller flag, limits and ACL plan).

---
