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.

Command line usage

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.

Viewing account information

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.

Getting specific information

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.

Filtering columns

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

Filtering the output using yq

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.

Filtering output

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
	  ...

Using multiple filters

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

Combining filters and columns

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

Checking the output and when not to use WHM API 1

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.

Where to go from here

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.