WHMCS module
The VorticPanel module for WHMCS runs the whole server lifecycle from WHMCS: it creates a server when an order is paid, suspends it when an invoice is overdue, unsuspends it when it’s paid, terminates it when the service is canceled, and changes its package on an upgrade or downgrade. Clients see their server in WHMCS’s client area, with its addresses, traffic and power buttons. It sells GPU instances the same way.
It works with WHMCS 8 on PHP 7.4 or newer, with PHP’s curl extension (WHMCS needs it too). WHMCS has to reach your panel over HTTPS: the module only sends the API key over HTTPS.
Much of what the module does is the same in the Blesta module, and is described once under The WHMCS and Blesta modules. This page covers installing it and what’s particular to WHMCS.
1. Install the module
Download it from Downloads in your account on vorticpanel.com. It’s a zip with a modules folder and a short README.
Unzip it into your WHMCS folder, the one with configuration.php in it, keeping its folders, so the module ends up in modules/servers/vorticpanel. On a server you reach over SSH, with your WHMCS folder in place of /var/www/whmcs:
cd /var/www/whmcs
unzip -o ~/vorticpanel-whmcs-1.6.2.zip 'modules/*'
In Plesk or cPanel, upload the zip in the File Manager to the folder with configuration.php, extract it there, and delete the README.txt it adds.
To update the module later, unzip the new version over the old one (-o replaces the old files without asking). Services and settings stay as they are.
2. Make an API key in the panel
- In the panel, go to Admin → API & webhooks, and under Panel API keys click New API key.
- Name it
WHMCS, and under Permissions click the Billing module preset. - Under Allowed IP addresses, add your WHMCS server’s IP address.
- Set Expires to No expiry. Create it, and copy the key (it starts with
pnl_): it’s shown once.
More about panel API keys is under Create a key and in Authentication and tokens.
3. Add your panel as a server in WHMCS
In WHMCS, go to Configuration → System Settings → Servers → Add New Server:
| Field | What to enter |
|---|---|
| Name | Anything, such as VorticPanel |
| Hostname | Your panel’s domain, such as panel.example.com |
| Module | VorticPanel |
| Username | Leave it empty |
| Password | The API key from step 2 |
| Secure | Ticked, so it connects over HTTPS |
Click Test Connection, then Save Changes. Then, under Create New Group, make a server group with this server in it; products pick a group.
Back in the panel, set Billing link under Settings → General to your WHMCS address, such as https://billing.example.com. Customers find it in the panel, and each customer’s page links to their client in WHMCS.
4. Set up a product
Create a product (type Server/VPS) or open an existing one, and on its Module Settings tab choose VorticPanel and the server group. The module then lists what’s in your panel:
| Setting | What it does |
|---|---|
| Package | The package the product sells, or a GPU offer for a GPU product |
| Location | The node group its servers go in. Leave it on the first choice, The package’s only node group, or the client’s choice, when the package is in one node group, or when clients pick (see below). |
| Operating system | What’s installed. The client chooses it in the panel, or a configurable option creates the server waiting for setup: the client picks the operating system when they first open it in the panel. |
| Usage when terminated | Bill it at once (the default) or Don’t bill: what happens to usage charged under Metric Billing that hasn’t been invoiced when the service ends. See When a service ends. |
| Immediate cancellations | For GPU products: Terminate straight away (the default) or At WHMCS’s daily run, when a client asks for an immediate cancellation. Servers always wait for WHMCS’s daily run. See When a service ends. |
| Pay from credit | For GPU products: On has clients pay for their hours from their account credit as they go, and suspends an instance when the credit runs out. See Paying from credit. |
| Hours of credit | With Pay from credit: how many hours of use the client’s credit has to cover for an instance to start, and below which they’re emailed to add funds. 2 when left empty. |
| Time out of credit | With Pay from credit: how long an instance stays suspended for running out of credit before it’s terminated, so its GPUs are free for other clients. See Time out of credit. 7 days when left empty. |
Pick Automatically setup the product as soon as the first payment is received so servers are made without anyone clicking.
A package that gives its servers graphics cards (GPU servers) is sold the same way: pick it as the product’s Package, and each server gets its cards as it’s made.
The server’s hostname is the one the client types when ordering (WHMCS asks for it on Server/VPS products). Without one, it’s vps and the service’s number, such as vps42, and the client can change it in the panel. A server waiting for setup keeps the hostname typed on the order; without one, the client chooses it when they set the server up.
Letting clients choose
A product sold in one node group, with one operating system, needs none of this. To let clients pick at order time, add configurable options with these names. The client’s choice wins over the product’s setting.
| Option name | Type | Each choice |
|---|---|---|
| Location | Dropdown | A node group’s name, exactly as under Nodes → Node groups in the panel, such as US-East. It’s always a node group, not a region: see Locations. |
| Operating System | Dropdown | A template’s name as OS templates in the panel shows it: the distribution and version, such as Ubuntu 24.04. For a GPU product, the container image’s name. |
| Extra IPv4 | Quantity | How many addresses the client wants on top of the package’s |
| Backups | Dropdown | A backup plan’s name as Backup plans in the panel shows it, such as Daily; None for no backups; or Package for the panel package’s own plan |
Clients see what you type, so to show them something friendlier than the node group’s name, write the choice as node group name|what clients see. WHMCS shows clients the part after the bar and gives the module the part before it: US-East|New York shows “New York” and places the server in US-East. The same works for operating systems, such as Ubuntu 24.04|Ubuntu 24.04 LTS.
In WHMCS:
- Go to Configuration → System Settings → Configurable Options and click Create a New Group. Name it (such as
VPS options), tick the products it’s for under Assigned Products, and save. - Click Add New Configurable Option. Set Option Name to
Locationand Option Type to Dropdown. - Type each choice into Add Option, such as
US-East|New York, give it a price (0 for no extra charge), and save. Add one choice per node group. - Add another option the same way, named
Operating System, with one choice per template, such asDebian 12andUbuntu 24.04. - For extra addresses, add an option named
Extra IPv4with Option Type set to Quantity, set the most a client can order, and price it per address. - To sell backups, add an option named
Backups, type Dropdown, with a choice per backup plan you offer (such asDaily|Daily backups) andNone|No backups, each with its price.
The option names have to match the table (capitals don’t matter). A choice the panel doesn’t recognize, or a node group that isn’t one of the product’s package’s, stops the order with a message on the service. Only configurable options count, not custom fields, whose text clients type themselves. Changing Extra IPv4 in an upgrade adds or removes addresses to match, and changing Backups moves the server to that plan.
The Backups choice is set once the server is made. When it can’t be, such as a choice that isn’t a backup plan’s name, the server is kept and linked to the service, and Create answers “The server was created, but its backups couldn’t be set” with the reason. Correct the option’s choice and click Create again: while the service is Pending, it only sets the server’s backups, and the service becomes Active.
SSH keys on the order
Add a custom field called SSH Key (type Text Area, shown on the order form) to let clients paste their public key when they order. What happens to it is under SSH keys from the order. When a key isn’t valid, WHMCS shows why on the service.
A private key pasted by mistake isn’t sent to the panel: the module clears it from the service’s SSH Key field and says so on the service. WHMCS may already have included it in the order’s emails, so ask the client to make a new key pair. Leave Show on Invoice unticked on the field, so keys don’t appear on invoices.
What happens when
| In WHMCS | In the panel |
|---|---|
| Create (an order is paid) | The client gets a panel account, linked to their WHMCS client ID (see Whose account a service uses). The server is created, and its address, hostname and ID (as the service’s Username) are saved on the service, with the root password when it’s built at once. |
| Suspend (an invoice is overdue) | The server is suspended, with WHMCS’s reason, such as Overdue on Payment |
| Unsuspend (it’s paid) | The server is unsuspended |
| Terminate (the service is canceled) | The server is destroyed and its addresses freed |
| Change Package (an upgrade or downgrade) | The server moves to the new product’s package, and extra addresses follow the Extra IPv4 option. A downgrade without an Extra IPv4 option removes the addresses the bigger package added. With a Backups option, the server’s backup plan follows it. |
Each one can be run again safely. Suspending a suspended server or terminating one that’s gone counts as done, and a create retried after a timeout doesn’t make a second server.
On the service, staff also get Start, Shut down, Restart, Force off, Reset root password and Refresh details. Reset root password sets a new one through the server’s guest agent and saves it on the service. Refresh details copies the server’s addresses and hostname from the panel onto the service. There’s no Change Password: the panel chooses root passwords itself.
Emails
The panel emails the client when their server is ready to set up, and again when it’s built, with its address and root password (unless you’ve switched those emails off). Leave the password out of WHMCS’s own welcome email for these products: for a server the client sets up themselves, WHMCS only knows a password it made up at order time, not the server’s. The service’s Username in WHMCS is the server’s ID (such as srv_8f2k1x7q), which usage billing tells services apart by; the server’s own user is root.
Upgrades and downgrades
Under each product’s Upgrades tab in WHMCS, tick the products a client can move to, and Configurable Options if they can change their extra addresses or backups. When the upgrade or downgrade is paid, WHMCS runs Change Package. What the server does then, and what’s refused, is under Upgrades and downgrades.
The client area
The service’s page in WHMCS shows the server as it is now: its status, hostname, addresses, resources and this period’s traffic. It keeps itself up to date: every few seconds while the server is starting, stopping, restarting or being built, and every half minute otherwise, without reloading the page.
Its buttons are what the panel lets the client do with the server right now, and they work without leaving the page:
| The server is | Buttons |
|---|---|
| Running | Restart, Shut down, Force off, Reset root password |
| Stopped | Start |
| Waiting for setup | Set up the server (Set up the instance for a GPU instance), which opens the panel to choose its operating system or image |
| Suspended, or busy (being built, reinstalled or moved) | None |
Shut down, Force off and Reset root password ask the client to confirm first, and so does Stop on a GPU instance. The buttons and links work only from the service’s own page in WHMCS, only on a server whose panel account is the client’s own, and only while the service is Active in WHMCS. After Reset root password, the new password is shown on the page once, with a button to copy it. For a GPU instance, the buttons are Start, or Restart and Stop, with its SSH command and JupyterLab link. When the panel serves JupyterLab over HTTPS, Open JupyterLab signs the client in, as Open control panel does.
Users the client has invited to their account keep to the permissions the client gave them: the buttons need View & Modify Product Passwords, and Open control panel and the panel links need Perform Single Sign-On. Without the first, the page shows the server with no buttons.
The page’s Actions list opens your panel in a new tab, already signed in (see Signing in from the billing panel): Open control panel, and the server’s own pages there, as far as the server allows. That’s Set up the server while it waits for setup; Console, Addresses and reverse DNS, Reinstall, Snapshots and Backups (when its package has them), Firewall and Settings once it’s built; and only Open control panel while it’s suspended. For a GPU instance, it’s Open control panel, with Set up the instance while it waits for setup and Console and logs once it’s set up (and JupyterLab when the panel serves it over HTTPS); while it’s suspended, only Open control panel is there.
The admin area
The service’s page in WHMCS’s admin area shows the server: its name and status, addresses, package, operating system, traffic and where it runs, with Open in VorticPanel, and its Panel account (see Whose account a service uses).
To link the service to a server that already exists, enter the server’s ID under Server ID and click Save Changes. To link a client to a panel account that already has their email, open the service’s Products/Services tab, enter the account’s ID under Client’s panel account, click Save Changes, then click Create again. When an account can’t be linked, the field is empty again after saving, and Configuration → System Logs → Module Log says why.
Client details changed in WHMCS (name, email or company) reach the panel account WHMCS made as soon as they’re saved; see Client details.
Charging by usage
The module tells WHMCS’s usage billing what each service used this month, as the panel measured it, and WHMCS charges for it on the client’s next invoice. You set the prices in WHMCS.
| Metric | What it counts |
|---|---|
| Traffic | A server’s traffic this month, in GB |
| GPU running hours | Hours a GPU instance’s container was running |
| GPU allocated hours | Hours a GPU instance existed, running or not: its cards, ports and address are held either way |
To charge for them:
- In WHMCS, go to Configuration → System Settings → General Settings, and on the Invoices tab tick Enable Metric Usage Invoicing. Without it, WHMCS shows usage but doesn’t bill it.
- Open the product under Configuration → System Settings → Products/Services, and go to its Module Settings tab. Under the module’s settings are the three metrics.
- Switch each one you charge for to On, click Configure Pricing, and choose how it’s priced:
- Per Unit: the same price for each GB or hour, such as $0.50 a GPU running hour;
- Quantity Included: free up to an amount, then a price for each one over it, such as 2,000 GB of traffic included and $0.01 a GB after that;
- Total Volume or Graduated: cheaper prices past set amounts.
- Click Save, then Save Changes.
Each calendar month’s usage is added to the service’s next renewal invoice as its own line, so sell these products on the Monthly billing cycle. To charge only for usage, such as a GPU product paid by the hour, set the product’s Payment Type to Recurring with a monthly price of 0.00. Don’t use Free: a free product doesn’t renew, so its usage wouldn’t be invoiced. WHMCS reads the numbers twice a day; staff see them under Metric Statistics on the service (with Refresh Now), and clients see theirs on the service’s page.
Usage billing finds each service by its Username, which the module sets to the server’s ID. Refresh details on the service sets it again if it was changed.
When a service ends
WHMCS bills usage on a service’s renewal invoices, so a service that’s terminated (canceled, or terminated by staff) would leave the usage since its last invoice unbilled. The module bills it instead: when it terminates the service, it reads the usage up to that moment from the panel, adds any earlier months WHMCS read but didn’t invoice, and prices them with the product’s own Metric Billing settings: what’s included, the price ranges, the client’s currency and the service’s billing cycle. Each metric and month becomes a line on one invoice, made at once and due the same day, such as “GPU running hours for train-1 (gi_7k2m9q), October 2026: 12.5 hours, 2 included (final usage)”. The client’s credit pays it as far as it goes; anything left is an unpaid balance on that invoice for them to pay, and WHMCS emails it as usual. If WHMCS won’t make the invoice, the lines are added as billable items instead, which WHMCS invoices at its next daily run.
WHMCS processes cancellation requests once a day, in its daily run, so a client who asks for an immediate cancellation of a GPU instance would keep running up GPU hours until then. For GPU instances, the module terminates the instance as the request comes in instead, which bills its hours up to that moment; WHMCS’s daily run then closes the request. An instance suspended for anything but running out of credit, in WHMCS or in the panel (such as for abuse), waits for WHMCS’s daily run, which leaves you time to look into it; delete the request under Clients → Cancellation Requests to keep it. To leave all of them to WHMCS’s daily run, set Immediate cancellations to At WHMCS’s daily run on the GPU product. Servers’ cancellations, and cancellations at the end of the billing period, always happen on WHMCS’s schedule.
A month a renewal invoice already billed part of is billed only for what came after, with what’s included counted once. The calculation is in Module Log (as FinalUsage) and the invoice in the client’s activity log. Terminating a service again, or twice at once, doesn’t bill it twice; a line WHMCS refuses is named in the activity log for you to add by hand. To leave usage on termination unbilled, set Usage when terminated to Don’t bill on the product’s Module Settings.
Traffic
Once a day, WHMCS’s cron asks the module for each server’s traffic this period and its disk size, and shows them on the service under Bandwidth and Disk, where WHMCS’s usage reports and overage billing can use them. This needs Update Usage Statistics ticked under Configuration → System Settings → Automation Settings.
GPU instances
Pick a GPU offer as the product’s Package, and the container image as its Operating system. With The client chooses it in the panel, or a configurable option, the instance is created waiting for setup: its cards, ports and address are held, and the client picks the image (and the SSH keys root takes) when they first open it in the panel; the client area shows Set up the instance until then. Add the SSH Key custom field (see SSH keys on the order) so clients can sign in over SSH from the start; JupyterLab works without one. The client area shows the instance’s cards, its SSH command and its JupyterLab link. GPU instances sign in with SSH keys from the client’s panel account, so there’s no root password. Terminating one deletes it with its /workspace. An instance keeps its offer: to move to a bigger one, the client orders the other product.
To charge by the hour instead of, or as well as, a fixed price, see Charging by usage.
Paying from credit
Usage is normally billed after it’s used, on the next invoice, so a client could run a GPU for hours, cancel and not pay that invoice. With Pay from credit on, a GPU product works as a prepaid account instead: clients add funds first (WHMCS’s Add Funds, under Billing in the client area), and their hours are paid from that credit.
- Starting: an instance is made only when the client’s credit covers its Hours of credit at the product’s prices. An order without enough credit waits: the service stays Pending, the client is emailed once with how much it needs, its page in the client area shows the same with an Add funds button (and says it’s starting once the credit covers it), and it’s made when the funds arrive (when the Add Funds invoice is paid), or at WHMCS’s next cron run otherwise. Staff see Waiting for credit on the service’s module tab, and Create there starts it at once when the credit covers it.
- While it runs: every five minutes, after WHMCS’s cron, the module prices each instance’s hours this month with the product’s Metric Billing and compares what the client owes (those hours, unpaid invoices and billable items not invoiced yet) with their credit balance. The client area shows the credit left and about how many hours it covers; staff see the same on the service’s module tab.
- Running low: when what’s left covers fewer than the Hours of credit, the client is emailed once to add funds.
- Running out: the instance is suspended with the reason “Out of credit: add funds to start it again”, and WHMCS emails the client as for any suspension. The service’s page in the client area says the credit ran out, with an Add funds button. Its
/workspace, address and ports are kept while it’s suspended. Once the client’s credit covers its Hours of credit again, it’s unsuspended: when the Add Funds invoice is paid, or at WHMCS’s next cron run otherwise. A suspension for any other reason isn’t lifted this way, including one staff made in the panel: an instance that was already suspended there when its credit ran out, or that staff suspended there for something else since, is left for staff, and isn’t terminated for being out of credit. - Out of credit for good: after the product’s Time out of credit (7 days by default) still suspended, it’s terminated and its GPUs are freed; the client is emailed beforehand with how long is left, and its final usage is invoiced as for any termination. WHMCS’s own overdue termination doesn’t do this, since no invoice is overdue.
- Paying: the module doesn’t take money itself. The hours go on the service’s renewal invoice, or on the final usage invoice made when it ends, and WHMCS pays those from the client’s credit.
To set it up:
- Price GPU running hours, and GPU allocated hours if you charge for them, under Metric Billing as in Charging by usage, with the product on Recurring, monthly, at 0.00.
- On the product’s Module Settings, set Pay from credit to On, Hours of credit to how many hours a client must have paid for in advance, and Time out of credit to how long an instance stays suspended for lack of credit before it’s terminated, such as
30m,12hor7d(7 days by default; see Time out of credit). - Let clients add funds: on the Credit tab of Configuration → System Settings → General Settings, turn on Add Funds and set a minimum and maximum deposit.
- Leave No Auto Apply Credit unticked (General Settings, Invoices tab), so WHMCS pays new invoices from the credit.
Time out of credit
Write the time with its unit:
| You write | It means |
|---|---|
1m, 30m |
1 minute, 30 minutes (m is always minutes) |
1h, 12h |
1 hour, 12 hours |
1d, 7d |
1 day, 7 days |
7 |
7 days: a number without a unit is days |
0 |
It stays suspended until you terminate it |
Before it’s terminated, the client is emailed with how long is left: a day before, or halfway through a time under two days. It’s never terminated before that email has gone out. The module checks after each of WHMCS’s cron runs, every five minutes, so a termination happens at the first run after the time is up; with a time shorter than that, such as 1m, the warning goes out at the first run after the suspension and the termination at the next, about ten minutes after the credit ran out.
WHMCS’s cron has to run every five minutes, as WHMCS asks for anyway; Utilities → Automation Status shows when it last ran. On Plesk, give the scheduled task the same PHP version as the WHMCS site (the site’s PHP settings): WHMCS needs ionCube, which is installed per PHP version, so a cron on another version fails while the site works. Suspensions, unsuspensions, orders made once credit arrived, terminations for being out of credit and the emails before them are in the client’s activity log. Allocated hours keep counting while an instance is suspended, because its cards stay held for it until it’s unsuspended or terminated.
Moving services from VirtFusion or Virtualizor
After the panel has imported a VirtFusion or Virtualizor panel’s servers, the services that sold them in WHMCS still use the old panel’s module. The zip comes with a small addon that moves them onto VorticPanel products in one go. Each service keeps its price, billing cycle, due date and status; only its product and server change, and it’s linked to the server the import made.
- Make a VorticPanel product for each kind of server you sold, as in Set up a product. Its package only matters for upgrades later: switching never changes a server.
- Go to Configuration → System Settings → Addon Modules, find VorticPanel: switch services, click Activate, then Configure and tick the admin roles that may use it. Those roles also need WHMCS’s Edit Clients Products/Services permission to switch services.
- Open Addons → VorticPanel: switch services. It lists every product that uses the VirtFusion or Virtualizor module. Beside each, choose the VorticPanel product its services move to, or leave it as it is.
- Click Preview. Each active or suspended service is listed with its server on VorticPanel, found by its ID on the old panel (VirtFusion’s server ID, Virtualizor’s VPS ID). Nothing has changed yet.
- Click Switch.
A service is left where it is when:
| Shown | Why |
|---|---|
| Not imported into VorticPanel | Its server wasn’t part of an import, or was left out of it |
| The service has no VirtFusion server ID (or Virtualizor) | The old module never recorded which server it was |
| More than one imported server has that ID | You imported two panels of the same kind with the same IDs, and the service’s server in WHMCS doesn’t say which. Link it by hand, below. |
| Services #… all point at the same imported server | Two services have the same server ID on the same old panel. Correct the wrong one in WHMCS, then preview again. |
| Its panel account belongs to WHMCS client #…, not this service’s client | The import linked the server’s panel account to another WHMCS client. Check which client the service should belong to. |
| … is already linked to service #… | Another service has that server |
When the server’s panel account has a different email from the WHMCS client, the service still switches, but the client’s buttons in the client area stay off until you link the account: give the client the account’s email in WHMCS, then enter the account’s ID under Client’s panel account on the service’s module tab (see Whose account a service uses).
Any service can also be switched by hand: change its product to the VorticPanel one, and enter the server’s ID (srv_…) as Server ID on its module tab.
Run it again whenever you like: switched services are no longer on the old products, so only what’s left shows. Once nothing uses the old products, delete them, and the old panel’s server in WHMCS.
Resellers
A reseller can run the module in their own WHMCS, with a token from their own account; see Resellers.
When something goes wrong
The message WHMCS shows comes from the panel. Every call the module makes is listed in the panel under Administration → API requests, with what it sent and what the panel answered; filter by the token’s name to see only WHMCS’s. In WHMCS, Configuration → System Logs → Module Log shows the same calls from WHMCS’s side, once its logging is switched on there.
| Message | What to do |
|---|---|
| Couldn’t reach the panel | Check the server’s hostname in WHMCS, that Secure is ticked, and that your WHMCS server can reach the panel on 443 |
| The panel’s server in WHMCS isn’t set to use HTTPS | Tick Secure on the server, and make sure its hostname doesn’t start with http:// |
| The panel already has an account for … that this WHMCS didn’t make | See Whose account a service uses |
| That didn’t work just now (shown to a client) | The panel’s own answer is in Module Log |
| Your user doesn’t have permission to … (shown to a client) | A user the client invited to their account is missing View & Modify Product Passwords (for the buttons) or Perform Single Sign-On (for the panel links). The account owner gives them under User Management. |
| This token needs one of these permissions | Make a new API key with the Billing module preset |
| This token can’t be used from … | Add WHMCS’s address to the key’s IP allowlist. Behind a proxy, see Authentication and tokens. |
| Open control panel shows the panel’s sign-in page | The key doesn’t have Customers: sign-in links: make a new one with the Billing module preset |
| Pay from credit is on, and the client has … of credit free; it needs … to start | Nothing to do: the service stays Pending, and the instance is created once the client’s added funds cover it. If it doesn’t start, check Utilities → Automation Status. See Paying from credit. |
| No node in … has room for … | No node in that node group has room for the package: add a node or free space there, then click Create again |
| No free IPv4 address | Add addresses to the IP pools attached to the node group’s nodes, then click Create again |
| The panel’s license needs attention | See License. Create, suspend, unsuspend and terminate keep working. |
Other answers are listed under Why an order can be refused.