Developer Documentation

Build plugins for Panelr.

Panelr's open plugin system lets developers connect any IPTV panel with an API. Build once, distribute to any Panelr installation.

What is a plugin?

A Panelr plugin is a PHP class that connects a Panelr installation to an IPTV panel's API. Every IPTV provider uses a panel to manage their streams and subscribers — XtreamUI, custom panels, proprietary systems. Panelr is panel-agnostic by design: instead of building native support for every panel that exists, Panelr uses plugins to bridge that gap.

When a provider installs your plugin, Panelr can automatically create lines, renew subscriptions, sync products, update bouquets, and manage subscribers — all through your panel's API, without the provider ever having to log in manually.

One plugin, many installations. You build and maintain one PHP file. You sign it individually for each client. Each signing produces a unique package cryptographically bound to that installation.
Looking to integrate Panelr into your own app or storefront? You don’t need a plugin — use the Panelr API instead. View API documentation.

How it works

The full lifecycle from development to a client's running installation:

  1. 1You build a PHP plugin class implementing PanelPluginInterface and upload it to your developer account at cloud.panelr.app.
  2. 2Panelr scans your file automatically — checking for syntax errors, security violations, and interface compliance.
  3. 3A client gives you their Installation ID from their Panelr dashboard.
  4. 4You sign the plugin for that installation in cloud.panelr.app — Panelr generates a signed ZIP locked to that Installation ID.
  5. 5The client installs the signed ZIP into their Panelr installation. Panelr verifies the cryptographic signature and file integrity on install.
  6. 6The client configures the plugin with their panel credentials. Panelr uses your plugin to automate their entire operation.

Getting started

Developer account

To build and distribute Panelr plugins you need a developer account. Login to your exsting Panelr Cloud account at cloud.panelr.app and enable developer access from your account settings. Once enabled, you'll have access to the My Plugins section where you can upload, manage, and sign your plugins.

Plugin skeleton

Create a new PHP file named after your class — for example MyPanelPlugin.php. The filename must match the class name exactly.

<?php

class MyPanelPlugin implements PanelPluginInterface
{
    private array $config = [];

    public function getName(): string
    {
        return 'My Panel Plugin';
    }

    public function getVersion(): string
    {
        return '1.0.0';
    }

    public function getCapabilities(): array
    {
        return ['products', 'activations', 'bouquets'];
    }

    public function getRequiredConfigFields(): array
    {
        return [
            [
                'key'         => 'api_url',
                'label'       => 'Panel API URL',
                'type'        => 'url',
                'required'    => true,
                'default'     => '',
                'description' => 'Base URL of your panel API',
            ],
            [
                'key'         => 'api_key',
                'label'       => 'API Key',
                'type'        => 'password',
                'required'    => true,
                'default'     => '',
                'description' => 'Your panel API key',
            ],
        ];
    }

    public function configure(array $config): void
    {
        $this->config = $config;
    }

    public function testConnection(): array
    {
        $ch = curl_init($this->config['api_url'] . '/ping');
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER     => ['X-Api-Key: ' . $this->config['api_key']],
            CURLOPT_TIMEOUT        => 10,
        ]);
        $response = curl_exec($ch);
        $code     = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        return $code === 200
            ? ['success' => true,  'message' => 'Connected successfully.']
            : ['success' => false, 'message' => 'Could not connect to panel.'];
    }

    // Implement remaining interface methods...
}
Declare only what your panel supports. Panelr hides UI controls for capabilities you don't declare. If your panel doesn't support bouquet updates, don't declare bouquets_update — your clients won't see controls that don't work.

Plugin structure

When you sign a plugin for a client, Panelr packages it into a ZIP containing three files. You only provide the PHP file — the other two are generated automatically.

  • {ClassName}.php — your plugin class file
  • plugin.json — manifest generated from your plugin settings
  • license.json — cryptographic license locked to the target installation

Naming rules

  • Your PHP filename must match your class name exactly: MyPanelPlugin.phpclass MyPanelPlugin
  • Class names must be unique across installed plugins
  • One class per file — multiple class definitions will fail the security scan

Interface reference

Every plugin must implement all methods of PanelPluginInterface. Every method returns an array containing at minimum a success key. Methods gated behind a capability are only called when that capability is declared in getCapabilities() — but all methods must still be present in your class.

Identity

getName(): string Always required
Returns the display name of the plugin shown in the Panelr admin.
getVersion(): string Always required
Returns a semver version string, e.g. "1.0.0".
getCapabilities(): array Always required
Returns an array of capability strings your plugin supports. See the Capabilities section for the full list.

Configuration

getRequiredConfigFields(): array Always required

Returns field definitions Panelr uses to render a configuration form in the admin. Each field is an array with:

  • key — stored in config JSON, passed back via configure()
  • label — form label shown to the admin
  • typetext, password, url, number, or select
  • required — boolean
  • default — default value
  • description — help text shown below the field
  • options — for select type only: ['value' => 'Label', ...]
configure(array $config): void Always required
Called by Panelr after loading your plugin, passing the saved configuration as a key-value array. Store in a private property and use in your API calls.

Connection

testConnection(): array Always required

Tests connectivity to the panel API. Called when an admin saves plugin settings.

['success' => true,  'message' => 'Connected successfully.']
['success' => false, 'message' => 'Could not connect to panel.']

Activations

createActivation(array $params): array activations

Creates a new line on your panel. Panelr passes product_id, bouquet_ids, duration_months, and notes. Return the new line details:

['success' => true, 'data' => [
    'panel_user_id'   => '1234',
    'xtream_username' => 'abc123',
    'xtream_password' => 'xyz789',
    'expiration_date' => '2027-01-01 00:00:00',
    'xtream_host'     => 'http://panel.example.com:8080', // optional
    'm3u_url'         => 'http://...',                    // optional
]]
renewActivation(string $panelUserId, array $params): array activations

Extends an existing line. Panelr passes expiration_date, product_id, duration_months, username, and password. Return the new expiration date:

['success' => true, 'data' => [
    'expiration_date' => '2028-01-01 00:00:00',
]]
cancelActivation(string $panelUserId, string $username, string $password): array terminations
Permanently terminates a line. Returns ['success' => true] on success.
enableActivation(string $panelUserId, string $username, string $password): array enable_disable
Re-enables a previously disabled line.
disableActivation(string $panelUserId, string $username, string $password): array enable_disable
Temporarily disables a line without terminating it.
getActivationInfo(string $panelUserId, string $username, string $password): array activations

Returns current status and details for a line. Required fields: status (active, expired, disabled, or banned) and expiration_date. Return any additional fields your panel provides.

Products

syncProducts(): array products

Fetches packages/products from your panel. Required fields per item: product_id, name, duration_months. Optional: connections, credits, panel_description.

Bouquets

syncBouquets(): array bouquets
Fetches bouquets/channel groups from your panel. Required fields: bouquet_id, name.
syncLineBouquets(string $panelUserId, array $params): array bouquets_update
Updates the bouquets assigned to an existing line. $params['bouquets'] contains the array of bouquet IDs to assign.

Other

syncLines(): array lines
Fetches all lines from your panel for bulk import. Required: panel_user_id, xtream_username, xtream_password, expiration_date.
getCreditBalance(): array credits
Returns the reseller credit balance from your panel as a numeric value: ['success' => true, 'data' => 1500].

Capabilities

Declare only the capabilities your panel actually supports. Panelr uses this to show or hide admin controls — undeclared capabilities are never displayed.

Capability What it enables
products Sync packages and products from the panel into Panelr
activations Create, renew, and view line details
terminations Permanently cancel a line
enable_disable Temporarily enable or disable a line
bouquets Sync bouquet and channel groups
bouquets_update Update a line's assigned bouquets
credits Display reseller credit balance in the dashboard
lines Bulk import all lines from the panel
trials Enable trial line creation workflow

Security rules

Plugin files are scanned automatically on upload. Files that violate these rules are rejected before storage.

Allowed

  • curl_* functions for HTTP requests to your panel API
  • json_encode, json_decode, urlencode, urldecode
  • date, time, strtotime, date_create
  • All standard string, array, and math functions

Blocked

  • System execution — exec, shell_exec, system, passthru, proc_open
  • Code evaluation — eval, assert, create_function
  • File system access — fopen, fwrite, file_put_contents, file_get_contents
  • Database access — mysqli_*, new PDO
  • File includes — include, require
  • Superglobals — $_GET, $_POST, $_SERVER, $_SESSION
  • Output — echo, print, var_dump
  • Obfuscation — base64_decode+eval chains, variable variables
One class per file. Your plugin file must contain exactly one PHP class. Multiple class definitions will cause the scan to fail.

Plugin Management

Everything after your plugin code is written happens in Panelr Cloud at cloud.panelr.app. This section walks through the full workflow — uploading your plugin, managing it over time, signing it for individual clients, and automating signing via the API.

Managing Plugins

Everything after your plugin code is written happens in Panelr Cloud at cloud.panelr.app. This section walks through the full workflow — uploading your plugin, managing it over time, signing it for individual clients, and automating signing via the API.

My Plugins dashboard showing two plugins with capabilities, install counts, and sign actions

Each plugin row shows:

  • Plugin name and class — the display name you set, plus the PHP class name and version badge.
  • Capabilities — the capabilities declared in your plugin, shown as badges. These determine which Panelr features your plugin enables for clients.
  • Installs — the number of unique installations currently running your plugin.
  • Added / Last signed — when the plugin was first uploaded and when you last issued a signed package.
  • Actions — sign the plugin for a new client, edit plugin details, download your source file, or delete the plugin entirely.
Signing History tracks every signed package you've issued across all plugins — which client, which installation, and when. Use it to audit your distribution or re-sign for a client if they need a fresh package.

Adding Plugins

Click Add Plugin from the My Plugins page to open the upload form. Fill in the plugin metadata and upload your PHP file — Panelr scans it immediately.

Add Plugin dialog with fields for name, version, description, capabilities, and file upload

The form fields:

  • Plugin Name — the display name shown to you and your clients. Doesn't need to match the class name.
  • Min App Version — the minimum Panelr version required. Clients on older versions won't be able to install your plugin. Set this to the version you developed against.
  • Description — a short summary shown alongside your plugin. Optional but recommended.
  • Author — your name or company. Shown in plugin details on the client's side.
  • Capabilities — check every capability your plugin supports. These must match what your getCapabilities() method returns — Panelr validates this during the scan.
  • Plugin File (.php) — your PHP class file. Must implement PanelPluginInterface. The file is scanned for security violations and interface compliance before it's accepted.

Click Upload & Scan to submit. If the scan passes, your plugin appears in My Plugins and is ready to sign. If it fails, you'll see specific errors — fix them and re-upload.

Updating an existing plugin? Edit the plugin from My Plugins and upload a new PHP file. The scan runs again on the new file. Existing signed packages for clients are not affected — they'll continue using the version they installed until they install a new signed package from you.

Signing Plugins

Signing is how you issue your plugin to a specific client. Every signed package is cryptographically locked to a single Panelr installation — it cannot be shared or reused on another installation.

Click Sign on any plugin to start the three-step signing flow:

Plugin signing wizard showing step 1: Enter Installation ID with a lookup button
  1. 1Enter Installation ID — your client provides their Installation ID, found in their Panelr Cloud dashboard. Enter it and click Look Up Installation to verify it exists.
  2. 2Confirm Installation — Panelr shows the installation details so you can verify you're signing for the right client. Confirm to proceed.
  3. 3Sign & Download — Panelr generates a signed ZIP package locked to that installation. Download it and send it to your client.

Your client uploads the signed ZIP into their Panelr installation. Panelr verifies the cryptographic signature and file integrity automatically — if anything has been tampered with, the install is rejected. Once installed, they configure the plugin with their panel credentials from their admin dashboard.

Re-signing. You can sign the same plugin for the same installation as many times as needed. Each signing produces a new package with a fresh signature — useful when you've uploaded an updated version of your plugin file.

Sign Plugin API

For developers distributing to many clients, Panelr provides a signing API that lets you automate the signing process programmatically. Instead of using the web interface for each client, you can sign and download packages via API calls from your own systems.

Login to cloud.panelr.app to view the api documentation to automate signing your plugins