Development and databases

Developing and automating with the cPanel API

Reviewed on 5 min read cPanel API automation

The cPanel UAPI lets you query and change an account's functions. The operations available depend on the version, the permissions and the services enabled; it does not grant administrative access to the whole server.

Start with a read query and check the response before automating creations, changes or deletions.

From SSH on the account itself

The local command uses the identity of the user you have signed in as. It does not ask for an extra token, but access is already authenticated by SSH and limited to that account.

To list the mailboxes:

/usr/local/cpanel/bin/uapi --output=jsonpretty Email list_pops

Check result.status and result.errors: getting a response does not mean the operation finished successfully. The command output includes a result wrapper; the UAPI HTTP response presents that data directly.

If you need to process the list, use a JSON parser rather than filtering text with grep or sed. For example, with jq installed:

/usr/local/cpanel/bin/uapi --output=json Email list_pops \
  | jq -er 'if .result.status == 1 then .result.data[]?.email else error("UAPI did not complete the query") end'

The list may contain private addresses. If you save it, do so outside the public root and with suitable permissions; > overwrites an existing file.

From an external system

Create a token in cPanel > Manage API Tokens, used only for the integration and with an expiry date. Treat it as an account credential: do not assume it only allows one operation because you created it for that. Revoke it when it is no longer used.

Use the server's secure cPanel hostname, with a valid certificate and port 2083. Not just any domain will do if it points somewhere else or its certificate does not cover that name.

Save the header in a private file, for example ~/.config/cpanel-api/curl.conf, outside the website and with 0600 permissions. Its content has this format; replace the placeholders using your secrets manager:

header = "Authorization: cpanel USUARIO_CPANEL:TOKEN"

The request does not need to include the token on the command line:

curl --fail --silent --show-error --max-time 30 \
  --config "$HOME/.config/cpanel-api/curl.conf" \
  'https://servidor.example:2083/execute/Email/list_pops'

Do not turn off TLS verification to get round a certificate error. Also check status and errors in the JSON: an HTTP 200 response can contain a UAPI failure.

List FTP accounts from PHP and Laravel

In a Laravel application, get the details from its protected configuration. The example uses the framework's HTTP client and validates both transport and result:

use Illuminate\Support\Facades\Http;

$server = config('services.cpanel.server');
$username = config('services.cpanel.username');
$token = config('services.cpanel.token');

if (!$server || !$username || !$token) {
    throw new RuntimeException('The cPanel configuration is missing.');
}

$response = Http::withToken($username.':'.$token, 'cpanel')
    ->timeout(30)
    ->get('https://'.$server.':2083/execute/Ftp/list_ftp')
    ->throw();

$data = $response->json();
if ((int) ($data['status'] ?? 0) !== 1) {
    throw new RuntimeException('cPanel did not complete the query.');
}

$accounts = $data['data'] ?? [];

Set server as a hostname, with no scheme or path, and do not take it from free-text visitor input. Do not log tokens, passwords or full responses containing client data. In PHP without a framework, apply the same checks with cURL or an HTTP library.

Operations that change data

Before scheduling a write, check the parameters and consequences of its function in the UAPI documentation.

  • Redirects: Mime/add_redirect lets you create them. Test with a development domain and a temporary type; check source, destination, www and path preservation before using a permanent redirect.
  • Create email: look at UserManager/create_user for new integrations. If you maintain code with Email/add_pop, check its compatibility and send passwords via POST, never in the URL.
  • Empty spam: SpamAssassin/clear_spam_box affects the spam of every address on the account, including the main one. It is not a connectivity test or a clean-up limited to one mailbox.

Check the status after a write. If the request times out, do not retry automatically: the operation may have been applied even though your program did not get the response. Design each automation to detect existing results and keep a log without secrets.

You may also find useful

Something wrong or out of date? Tell us and we will review it.