4 September 2021
cPanel servers have APIs that let you do most of the admin tasks you can do via the grahpical interface from the command line. cPanel users with shell access can use the uapi utility, and administators can also use whmapi1. Both tools are thoroughly documented in the cPanel documentation, so I won’t cover all the options. Instead, I will show some of the basics and provide some tips and tricks.
whmapi1
takes a function and, optionally, one or more key-value pairs (more about them shortly). It also has an --output
option that lets you format the output. By default, the output uses YAML but you can change that to JSON or XML.
As at September 2021 there are over 600 functions you can use. You can run the --help
option to get a full list, though you probably find it easier to navigate the online documentation.
I should also mention that WHM API1 documention says that you always need to run whmapi1
using the full path to the cPanel binary on CloudLinux servers. This is not necessarily the case (whmapi1
is often a symbolic link to the cPanel binary). However, I will use /usr/local/cpanel/bin/whmapi1 in all the examples.
To start things off, one of the many available functions is accountsummary
. As you might expect, this returns lots of information about one or more accounts. Here is what information is returns for the user example:
# /usr/local/cpanel/bin/whmapi1 accountsummary \ user=example --- data: acct: - backup: 1 disklimit: 500M diskused: 65M domain: example.com email: support@catalyst2.com inodeslimit: unlimited inodesused: 2838 ip: 84.18.206.207 ipv6: [] is_locked: 0 legacy_backup: 0 mailbox_format: mdbox max_defer_fail_percentage: unlimited max_email_per_hour: 300 max_emailacct_quota: unlimited maxaddons: 1 maxftp: 1 maxlst: "*unknown*" maxparked: 1 maxpop: 1 maxsql: 1 maxsub: 1 min_defer_fail_to_trigger_protection: 5 outgoing_mail_hold: 0 outgoing_mail_suspended: 0 owner: root partition: home plan: c2-MegaDeal shell: /usr/bin/bash startdate: 21 Jun 03 18:07 suspended: 0 suspendreason: not suspended suspendtime: 0 temporary: 0 theme: paper_lantern uid: 1482 unix_startdate: '1622740024' user: example metadata: command: accountsummary reason: OK result: 1 version: 1
As said, by default the output uses YAML. The data.account node lists all the account information, and the metadata node shows information about the command itself (i.e. whether or not it completed correctly). The accountsummary
function I ran provides a nice overview of basic account details.
Often, you want just a specific field rather than a long list with data. There are two sets of functions you can use:
api.columns.enable
limits the output to specific columns.api.filter.enable
lets you match fields you define. For instance, you can filter the output of a function where a specific field has the value example.Let’s return to the accountsummary
command I used above to illustrate how filters work. If you just want to know, say, how much disk space the user example uses then you can use api.columns.enable to limit the output to just that field:
# /usr/local/cpanel/bin/whmapi1 accountsummary \ api.columns.enable=1 \ api.columns.a=diskused \ user=example --- data: acct: - diskused: 65M metadata: columns: invalid_msg: None command: accountsummary reason: OK result: 1 version: 1
And to report on multiple fields you can use multiple api.columns
key-value pairs. In the below example I use a second filter to get both the disklimit and diskused fields:
# /usr/local/cpanel/bin/whmapi1 accountsummary \ api.columns.enable=1 \ api.columns.a=diskused \ api.columns.b=disklimit \ user=example --- data: acct: - disklimit: 500M diskused: 65M metadata: columns: invalid_msg: None command: accountsummary reason: OK result: 1 version: 1
The above commands still include quite a bit of extra data, such as the nodes and metadata. If you just want a key and value – or perhaps just a value – then you can either use utilities such as grep and awk or a YAML parser such as yq. For instance, you can print just the disklimit and diskused fields under data.acct like so:
# /usr/local/cpanel/bin/whmapi1 accountsummary \ api.columns.enable=1 \ api.columns.a=diskused \ api.columns.b=disklimit \ user=example \ | yq eval '.data.acct[]' - disklimit: 500M diskused: 65M
And you can also get just a value (without the key):
# /usr/local/cpanel/bin/whmapi1 accountsummary \ api.columns.enable=1 \ api.columns.a=diskused \ api.columns.b=disklimit \ user=example \ | yq eval '.data.acct[].diskused' - 65M
If you want to learn more, we got a separate article about parsing JSON and YAML files that has more examples.
As you start using WHM API 1 you are likely to find that filtering is pretty essentials. The official documentation should be your first call but a few more examples of how to use filters might help you get started.
The listsuspended
function returns information about suspended accounts. The output looks like this:
# /usr/local/cpanel/bin/whmapi1 listsuspended --- data: account: - is_locked: 0 owner: example reason: Defunct time: Wed Jun 20 09:32:03 2018 unixtime: '1529483523' user: examplary - is_locked: 0 owner: root reason: Unknown time: Fri Nov 30 15:28:03 2018 unixtime: '1543591683' user: example ...
I truncated the output as the list was quite long. To get more specific information I can use a couple of api.filter
rules. For instance, I can apply the filter on the owner field and use example as the argument. That gives me all suspended accounts where the owner is example:
# /usr/local/cpanel/bin/whmapi1 listsuspended \ api.filter.enable=1 \ api.filter.a.field=owner \ api.filter.a.arg0=example --- data: account: - is_locked: 0 owner: example reason: Defunct time: Wed Jun 20 09:32:03 2018 unixtime: '1529483523' user: examplary ...
If that example made sense then we can take it one step further. You can do multiple comparisons by using more than one filter. For instance, you might want to return data for all suspended accounts that are owned by example and were suspended before 01/01/2021. The output of the listsuspended
function includes the date the account was suspended as a Unix timestamp, so you can check if the unixtime field is less than $(date -d '01/01/2021' +"%s")
. If that command looks weird, it takes the date 01/01/2021 and formats it as a Unix timestamp.
To filter the output on the owner and unixtime fields you simply add a second set of filter rules. In addition, you need to specify that the filter for the Unix time is a numeric comparison and that the unixtime field should be less than the value you provide. To check if a number is less than a value you can use lt. So, the final command is:
# /usr/local/cpanel/bin/whmapi1 listsuspended \ api.filter.enable=1 \ api.filter.a.field=owner \ api.filter.a.arg0=example \ api.filter.b.field=unixtime \ api.filter.b.arg0=$(date -d '01/01/2021' +"%s") \ api.filter.b.type=lt
You can also combine api.filter.enable
and api.columns.enable
. A common use-case for this is listing the PHP version for a domain. There is currently no easy way to retrieve that information but you can use two filters to get it.
# /usr/local/cpanel/bin/whmapi1 php_get_vhost_versions \ api.filter.enable=1 \ api.filter.a.field=vhost \ api.filter.a.arg0=example.com \ api.columns.enable=1 \ api.columns.a=account \ api.columns.b=vhost \ api.columns.c=version --- data: versions: - account: example version: ea-php74 vhost: example.com metadata: columns: invalid_msg: None command: php_get_vhost_versions reason: OK result: 1 version: 1
Let’s break that down…
/usr/local/cpanel/bin/whmapi1 php_get_vhost_versions
retrieves PHP information about all virtual hosts on the server.api.filter.enable=1
enables filtering.api.filter.a.field=vhost
tells whmapi1
that I want to filter the output by the vhost field.api.filter.a.arg0=example.com
specifies that the value of the vhost field should match example.com.api.columns.enable=1
tells whmapi1
that I want to only display specific columns.api.columns.a=account
, api.columns.b=vhost
and api.columns.c=version
are the field that should be printed.And you can again pipe the output to yq
to print only key-value pairs (and not the nodes):
# /usr/local/cpanel/bin/whmapi1 php_get_vhost_versions \ api.filter.enable=1 \ api.filter.a.field=vhost \ api.filter.a.arg0=example.com \ api.columns.enable=1 \ api.columns.a=account \ api.columns.b=vhost \ api.columns.c=version \ | yq e '.data.versions[]' - account: example version: ea-php74 vhost: example.com
When you use filters it is always useful to double-check the output. For instance, to check if the last command really returns accounts that were suspended before 01/01/2021 you can run the same command again but change api.filter.b.type
to gt (greater than) to check if the output makes sense. This is particularly important when you start using whmapi1
to change values. Like many command line tools, whmapi1
is very useful, but it can also be destructive.
In practice, you are most likely to use the utility to automate certain task. If you regularly review the disk usage for accounts or want a daily report of suspended accounts then whmapi1
is ideal. You would run the same command every so often, or maybe run a series of commands in a script. Similarly, the utility is also really useful if you want to do things like updating the PHP version for all domains that run a certain PHP version.
For other tasks the grahpical interface is more useful. For instance, terminating a cPanel account is best done via WHM. The action can’t be undone, and with whmapi1
you don’t get the “are you sure about this” dialogue. Using the grahpical interface may take a minute longer, but it avoids embarrassing accidents.
In this article I looked at just two functions: accountsummary and listsuspended. There are roughly 600 other functions. I cover some of them in other articles:
Other than that, browse through the official documentation and look for functions that look useful.