Configuring the module is three ordered steps. Get an API key from your Xtream AI Panel. Register your panel in the WHMCS addon so the module knows where to talk. Create a WHMCS product that uses the xtreamai server module, and tie it to a package and a set of bouquets on that panel. Each step takes about a minute if you already have the values on hand.

This page assumes the module is already installed and activated. If it is not, jump back to Install first.

Step 1. Obtain a Panel API key

The API key is how the module proves to your panel that it is entitled to create lines, adjust credits and read the catalog. The panel decides what each key is allowed to do based on the scopes you tick at issuance time. The module needs a small, specific set of scopes; picking them correctly here saves you from 403 insufficient_scope errors later on.

If you are a panel administrator

Log in to your Xtream AI Panel with your admin account. Open Settings → Panel API Keys. Click Create key, fill in a label (WHMCS-production-2026 is a reasonable convention), and tick the scopes.

If you are a reseller

Log in to your reseller area on the panel. Open Settings → Panel API Keys. If you do not see the tab, your admin has not yet enabled the can_create_api_keys permission on your member group. Ask them to tick Reseller settings → Member groups → Can create API keys for your group. Once the tab appears, click New key.

Which scopes to tick

The recommended scope sets depend on which kind of product you will provision.

For Line products only (both reseller and admin keys):

  • lines:read
  • lines:write
  • packages:read
  • bouquets:read

Add streams:read and vods:read if you plan to use the Catalog tab in the addon to browse the panel's live channels and VOD entries. They are read-only and cost nothing to include.

For Sub-Reseller products (admin key only), add on top of the Line scopes:

  • resellers:read
  • resellers:write
  • subresellers:write

The resellers:read and resellers:write scopes are admin-only. The panel refuses to attach them to a reseller key at issuance. If you plan to sell Sub-Reseller products, the key you paste into the module must come from a panel admin account. See Reseller vs Admin Keys for the full matrix.

With a reseller key, add subresellers:read (See sub-resellers on the panel) if you want the addon's Sub-Resellers tab to list your own sub-resellers and their credits (module 1.12.0 and later), and subresellers:credits (Transfer credits to sub-resellers) to transfer credits from your own balance to them (module 1.13.0 and later). Both need Can Create Subresellers on your member group. A key's scopes cannot be edited later: to add it, create a new key and paste the new token on the panel entry.

Leave the optional fields (IP allow-list, rate limit, expiration) empty for now. You can tighten them later without regenerating the key.

Click Save. The panel shows the full token on the screen, in the form:

pk_live_<12-char prefix>.<43-char secret>

Copy it immediately. Only the prefix is retrievable later; the secret half is displayed once and never again.

If you close the dialog without copying the token, the key is not lost, but the secret is. You will have to rotate the key from the same page to get a new secret. Full contract in Panel API Authentication.

Step 2. Add your panel to the addon

Now open WHMCS. Go to Addons → Xtream AI Panel → Panels, and click Add Panel. The form has one column of fields; fill them in as follows.

Field reference

Field Purpose
Panel name Free-text label for your own bookkeeping. Shown in the panel picker on WHMCS products and in the module logs. My main panel is a fine starting value.
API URL The base URL of your Xtream AI Panel, including the scheme and no trailing slash. For example, https://panel.example.com. Use the domain only: do not add /panel-api/v1, and do not add the random panel folder you see in the browser when you log in (for example https://panel.example.com/6390c2dde594413b). The module appends the path segments itself. With the folder in the URL most actions still work, but the live panel check on the service tab fails with HTTP 404.
M3U URL Optional. The M3U playlist URL your customer plugs into their IPTV app. Shown on the client-area card as Connection URL if set, hidden if left empty. Both URLs accept the {username} and {password} placeholders, replaced per client with the line credentials (URL-encoded); any other {...} is left untouched. Example: http://panel.example.com:8080/get.php?username={username}&password={password}&type=m3u_plus&output=ts.
EPG URL Optional. The EPG (XMLTV) URL your customer loads for the TV guide. Shown on the client-area card as EPG URL if set, hidden if left empty. Same {username} and {password} placeholders as the M3U URL. Example: http://panel.example.com:8080/xmltv.php?username={username}&password={password}.
API access key The full pk_live_... token you copied in Step 1. Stored encrypted at rest with WHMCS's own encrypt() helper; never rendered, never logged.
Key type Either Reseller or Admin. This must match what the token actually is. A reseller token attached as Admin, or an admin token attached as Reseller, will surface confusing errors later.
Admin owner member_id Only shown when Key type is Admin. Numeric member id (the id column of the reseller record on the panel) that will own every line this panel entry creates. Required for admin keys. If you are a panel administrator whose token belongs to a reseller record on the panel, use that reseller's id here.
Verify SSL On by default. Leave it on for production. Only disable it if your panel serves an internal or self-signed certificate you know is valid. Disabling shows a persistent warning banner in the admin UI.
Active On by default. Only inactive panels are hidden from the WHMCS product picker. Turn it off for retired panels you want to keep on file.

Verify the connection

Press Test Connection before you save. The module calls GET /panel-api/v1/me on the panel with the token you pasted, without going through the encrypted-at-rest storage yet, so the test works on unsaved credentials.

A successful test looks like this:

Connected (Group: RESELLER, Credits: 42.50)

That message means the token is valid, the panel accepted it, and the module resolved the identity behind the key. The Group value and the Credits value come straight from the panel and are only shown when they exist.

If the test fails, the message printed under the button is deliberate. Common ones:

  • Panel authentication failed. The token was mis-copied. Paste it again.
  • Could not reach the panel. DNS is wrong, the panel is offline, or your WHMCS host cannot reach the panel over HTTPS.
  • The panel is temporarily unavailable. The panel returned 503; try again shortly.
  • Any TLS-related error. Your panel's certificate is misconfigured, or Verify SSL is on and it should not be. Check the certificate before disabling verification.

Every failure is safe to retry. The connection test is a pure /me read and has no side effects on the panel.

When the test reads Connected, click Save on the form. The panel entry is now stored and encrypted, and it will show up in the panel picker of every WHMCS product that uses the module.

Step 3. Create a product that provisions through the module

The last step ties a WHMCS product to your panel. In WHMCS admin, go to Products/Services → Create a new product.

Under Details, pick a product type of Hosting Account (the naming is historical; WHMCS uses it for any kind of provisioned service, not just web hosting). Give the product a name your customers will recognize, and pick a group. Save the basic details.

Now open the product's Module Settings tab. In the Module Name dropdown, choose xtreamai. WHMCS reloads the tab and the module's config options appear.

Module config options

Option Purpose
Panel Dropdown of every active panel you added in Step 2. Pick the one this product provisions against.
Package Type Official or Trial. Purely a filter on the next dropdown; it changes which packages the module lists but has no effect on what gets stored.
Package Dropdown of every package the selected panel exposes, filtered by Package Type. Each entry shows the package name and duration. This choice is what the module sends as package_id on POST /lines at CreateAccount time, and again at Renew.
Bouquets Multi-select picker of every bouquet the panel makes available to the caller. The picker is searchable; on a large catalog this saves scrolling. The selected bouquets are what every new line for this product will carry. If customers will ever upgrade or downgrade into this product, pick only bouquets that belong to the Package selected above: on a product change the panel refuses any bouquet that is not part of the target package, and the change does not go through.
Account Type Line (default), Sub-Reseller or Credit top-up (existing Sub-Reseller). Line creates an IPTV line on POST /lines. Sub-Reseller creates a reseller account on POST /resellers. Credit top-up adds the configured credits to an existing Sub-Reseller account on the same panel, through POST /resellers/{id}/billing/adjust.
Credits Shown when Account Type is Sub-Reseller or Credit top-up. On a Sub-Reseller product it is the initial credit balance the panel assigns on creation, and the same value is added again on every renewal. On a Credit top-up product it is the amount every order adds to the client's existing Sub-Reseller account; a configurable option on the product named credits (also credit_amount or topup_credits) replaces it, which is how one product can sell 100, 500 and 1000 credit packages at different prices.
Max Connections Optional per-line concurrent-connection cap. Leave at 0 to inherit the package's own count; 0 never means unlimited, the Panel API does not create unlimited lines. Values from 1 to 100 override the package. This field only takes effect when the panel entry's Key type is Admin; reseller keys silently ignore it. The same absolute value applies on a product change that moves the line to another package: set 5 and the line ends up on 5, set 0 and the line takes the new package's own connection count. To let the customer pick the count, see the configurable option below.
Suspend action Line products only. Disable the line on the panel (default) disables the line when WHMCS suspends the service and enables it again on unsuspend. Leave the line untouched, let it expire never touches the panel on suspend or unsuspend: the line keeps working until its own expiry date. Module 1.5.3 and later.
Customer username Shown with Account Type Line and Sub-Reseller, hidden on Credit top-up. Generated by the module (default) keeps the module's credential generator in charge of the username. Customer types it in the "Line username" or "Reseller username" custom field takes the username from a WHMCS custom field on the product instead: Line username on a Line product, Reseller username on a Sub-Reseller product. The field, the checks and the messages are in Letting the customer choose the username below (Line products since module 1.9.0, Sub-Reseller products since module 1.10.0).
Customer password Shown with Account Type Line and Sub-Reseller, hidden on Credit top-up. Generated by the module (default) keeps the generator from the addon's General Settings in charge. Customer types it in the "Panel password" custom field takes the password from a WHMCS custom field on the product instead: the field, the rules and the note on where the value lives are in Letting the customer choose the password below (module 1.10.0 and later).
Top-up scope Credit top-up products only, and only shown when Account Type is Credit top-up. Any reseller on the panel (default) lets the customer top up any reseller account of that panel through the Reseller username custom field, whether or not WHMCS created that account: the module looks the username up on the panel itself. Only this client's linked Sub-Reseller accounts accepts only usernames that match a Sub-Reseller service of the same client linked on this panel and refuses anything else with The reseller username "<value>" does not match any of this client's linked Sub-Reseller accounts on this panel., without querying the panel. Both scopes check the typed username in the cart before payment (module 1.9.1 and later) and again when the module creates the service; with Only this client's linked Sub-Reseller accounts a customer who is not signed in is not checked in the cart, because the cart has no account list to compare the value against, so that username is only checked when the service is created. The cart check needs an admin key on the panel entry and never blocks an order when the panel does not answer. A product created before 1.8.2 has no stored value and behaves as Any reseller on the panel. The username is read from a custom field named Reseller username, Panel username or Sub-Reseller username, in either half of a WHMCS field name; a top-up product that carries a single custom field uses it whatever that field is called (module 1.9.4 and later).
Sub-Reseller Member Group ID Only shown when Account Type is Sub-Reseller. Numeric id of the panel member group new sub-reseller accounts land in. Required when the panel entry's Key type is Admin: the module refuses the order with Set the Sub-Reseller Member Group ID in this product's Module Settings: with an Admin panel key the panel needs the numeric id of the member group the new account belongs to. before it calls the panel, so nothing is created. Read the id from the panel's Member Groups page. Reseller keys ignore the option: the group comes from the sub-reseller setup on the panel.

Save the product. The next order for this product runs the module's setup, which maps onto the exact panel calls described in Provisioning Modes.

When the setup runs

At the end of the same Module Settings tab the module asks when to run the setup for a new order: as soon as an order is placed, as soon as the first payment is received, when you accept the order manually, or never. This is a per-product choice and the only thing that decides when provisioning happens.

  • Paid products are happy with as soon as the first payment is received: the line is created as soon as the invoice is paid.
  • Trial products priced at 0.00 raise no invoice at all, so as soon as the first payment is received never fires and the order stays Pending until an admin accepts it. Choose as soon as an order is placed for those products, so a trial order provisions itself as the customer places it.
  • When you accept the order manually keeps every order in Pending until you accept it from Orders → Pending Orders, whatever the amount.
  • Never leaves provisioning entirely in your hands: nothing is created until you press Create on the service page.

If you cancel a Pending order in WHMCS, WHMCS can show it as an order with an outstanding cancellation request; that is WHMCS's own order bookkeeping, not a module error. See Troubleshooting when an order does not provision itself.

Selling extra connections with a configurable option

One product per connection count gets unwieldy fast. Instead, attach a WHMCS Configurable Option to the product (System Settings → Configurable Options, create a group, add the option, assign the group to the product) and let the customer choose at checkout. The module (1.2.0 and newer) recognises the option by its name. Matching is case-insensitive, spaces and hyphens count as underscores, and anything after a | is ignored, so extra_connections|Extra Connections displays as "Extra Connections" and still matches.

Option name Semantics Suggested WHMCS type
extra_connections (also Extra Connections, additional_connections) Added on top of the base count. The base is the product's Max Connections when it is non-zero, otherwise the connection count of the panel package the product points at (the module reads it from GET /packages). Quantity from 0 to whatever you want to sell, priced per unit. On a 1-connection package a slider from 0 to 4 yields lines with 1 to 5 connections, and 0 adds nothing to the price.
max_connections (also Connections) Replaces the base count outright. 0 falls back to Max Connections, then to the package. Dropdown with 1, 2, 3... when every count has its own flat price.

If both are present, extra_connections is added on top of max_connections. The resolved number is sent as max_connections on POST /lines at CreateAccount, on every Renew (module 1.5.3 and later, since the panel's renew re-applies the package count), on Sync line to panel, and on every ChangePackage, which is also what WHMCS runs when a customer changes the option later through Upgrade/Downgrade Options and pays the upgrade invoice. Because the value is always sent when the option exists, a customer moving the slider from 2 back to 0 gets the package count back instead of keeping the old cap. The upper bound is 100, the same clamp the panel applies.

As with Max Connections, this needs an Admin key on the panel entry: max_connections is admin-only on the Panel API, and on a reseller key the module drops the field and the panel keeps the package count. Sub-Reseller products ignore both options.

Letting the customer choose the username

Module 1.9.0 and later on Line products, and module 1.10.0 and later on Sub-Reseller products too. With Customer username set to Customer types it in the "Line username" or "Reseller username" custom field, the username of every new account comes from a WHMCS custom field on the product instead of the module's generator. The option shows with both Account Types and is hidden on Credit top-up products. Add that field under Products/Services → your product → Custom Fields.

On a Line product:

  • Field Name: Line username (also accepted: Username, Panel username). WHMCS field names can carry a visible label after a pipe, as in Line username|Username for the panel: both halves count, so the accepted name can sit in either one, and a product that carries a single custom field needs no special name at all because that field is the one checked (module 1.9.4 and later).
  • Field Type: Text Box.
  • Show on Order Form: ticked, so the customer types the username at checkout.
  • Required: tick it if you do not want orders without a username.
  • Validation: ^[A-Za-z0-9_-]{3,32}$, so WHMCS rejects an invalid value before the order is placed. The module applies the same rule when it creates the service either way.

On a Sub-Reseller product the same list applies with a different field name: Field Name Reseller username (also accepted: Sub-Reseller username, Panel username, Username). Both halves of a name like Reseller username|Reseller username on the panel count, and a Sub-Reseller product that carries a single custom field uses that field whatever it is called in the cart (module 1.10.0 and later).

With the field in place, the module validates the value (3 to 32 letters, digits, dashes or underscores) and asks the panel whether that username is already used, both when the cart takes the order and again when the service is created. A username that is free is used as typed and the password comes from the addon's credential settings, or from the customer's own field when Customer password is on (see Letting the customer choose the password below). A username that is taken, or one that does not fit the format, stops that step and leaves the order pending in WHMCS for an operator to resolve from the service page. The module never attaches an existing panel line to a customer order, so a customer-chosen username can only create a new line: nobody can take over another customer's line, expiry or password. A username that was free at checkout can still be taken by the time the invoice is paid; correct the value on the WHMCS service and run Create again, or ask the customer for another one.

On a Sub-Reseller product the "already taken" lookup against the panel runs only when the panel entry's Key type is Admin: the cart then answers The reseller username "X" is already taken. Choose another one. and the service creation answers The reseller username "X" is already taken on this panel. Ask the customer to choose another one., leaving the order pending. With a Reseller key the module does not look the name up itself: the cart accepts it and the panel refuses a duplicate when the account is created, so the order stays pending with the panel's own message. A value that does not fit the format answers The username "X" is not valid: use 3 to 32 letters, digits, dashes or underscores. in the cart and at creation, and a panel that does not answer never blocks the cart, because the username is checked again when the service is created, exactly as on a Line product (module 1.10.0 and later).

Leave the option at Generated by the module (default), or the custom field empty, and usernames are generated exactly as before. Credit top-up products ignore the option, and it is hidden on them. The exact messages the cart and the service creation return are listed in Troubleshooting and in Provisioning Modes.

Letting the customer choose the password

Module 1.10.0 and later, on Line and Sub-Reseller products. With Customer password set to Customer types it in the "Panel password" custom field, the password of every new account comes from a WHMCS custom field on the product instead of the generator in the addon's General Settings. Add that field under Products/Services → your product → Custom Fields:

  • Field Name: Panel password (also accepted: Password, Line password, Reseller password). Both halves of a WHMCS field name such as Panel password|Password for the panel count, so the accepted name can sit in either one.
  • Field Type: Password is the recommended type, so WHMCS treats the value as a secret on the order form and on the service.
  • Show on Order Form: ticked, so the customer types the password at checkout.
  • Required: tick it only if every order must carry a password.

The module accepts 8 to 32 characters with no spaces and none of % & ? # / \ + " < > (" < > are refused from module 1.14.1, matching the panel); every other character is fine, including @ $ = : ; ! * ( ) ' ~ , . - _. A value that does not fit stops the order form with The password is not valid: use 8 to 32 characters without spaces and without % & ? # / \ + " < > and, when the order gets that far, stops the service creation with the same message and leaves the order pending in WHMCS. Leave the option at Generated by the module (default), or the custom field empty, and passwords are generated exactly as before. The module never displays the password and never writes it to the Module Log.

Where the chosen password lives. As soon as the account is created the module empties that custom field on the WHMCS service, and the password stays only in the service's Password field, like a generated one, which is where the customer sees it in the client area. Two things to keep in mind during the window before the service exists (a pending order, a payment not confirmed yet): the value is still sitting in the custom field then, and if your WHMCS Order Confirmation email template renders custom fields, the password can travel in that email. Use a Password custom field and review that template if you turn the option on for a product.

A small note on billing cycles

Renewals sync WHMCS's nextduedate to the panel's exp_date. If the WHMCS billing cycle and the panel package duration disagree, the two systems drift on each renewal in the direction of the panel value. A 30-day package on a monthly WHMCS cycle drifts a day or two per renewal, which is fine. A 1-year panel package attached to a monthly WHMCS cycle jumps a year ahead every time, which is almost certainly a misconfiguration.

Keep the WHMCS billing cycle aligned with the panel package duration and the two systems agree in perpetuity.

What Sub-Reseller products need in addition

Sub-Reseller products are optional and only work with an admin key. On top of the checklist above they need the resellers:read, resellers:write and subresellers:write scopes on an Admin panel entry with a valid Admin owner member_id, and a valid Sub-Reseller Member Group id on every product. That id must match a real member group on the panel (read it from the panel's Group Permissions page); otherwise provisioning fails with The panel rejected the request values.

The Provisioning Modes page walks through the exact panel calls for Sub-Reseller lifecycle, including the known limitation on Suspend, Unsuspend and Terminate.

What Credit top-up products need

A Credit top-up product adds credits to an existing Sub-Reseller account on that panel; it never creates an account. On top of the general checklist above, it needs:

  1. An admin key on the panel entry, exactly as for Sub-Reseller products.
  2. A destination to credit: either a Sub-Reseller service of the ordering client that is Active in WHMCS and linked to an account on the same panel (services created through the module are linked from the start; an account that existed before is linked once with Bulk tools → Link), or the Reseller username custom field, ticked Required and Show on Order Form, which the customer fills in and the module resolves against the panel when the product's Top-up scope allows that lookup. Without the field the module only gets it right when the client has exactly one linked Sub-Reseller service on that panel.
  3. A non-zero amount, from the product's Credits value or from a configurable option named credits.
  4. The Top-up scope you want, as described in the option table above.

The Provisioning Modes page walks through the panel call behind a top-up and the messages the module returns when the destination or the amount is missing.

Where to go next

The module is configured. The next thing to read depends on what you want to learn.

  • Reseller vs Admin Keys. The complete capability matrix, feature by feature. Useful before you commit to a key type.
  • Provisioning Modes. How Line, Sub-Reseller and Credit top-up each map to panel API calls.
  • Troubleshooting. The failures that come up most often and how to resolve them.