To use the WHMCS API from another server, create an API role and an API credential in the admin area, add the caller's IP address to the allowed list, then send an HTTPS POST to includes/api.php with the identifier, the secret, an action name and responsetype=json. Code that runs inside WHMCS calls the localAPI() function instead, without an identifier or secret.
I checked every action name, parameter and menu path below against the official WHMCS documentation on 10 October 2026. This guide covers calling WHMCS. Reacting to events inside WHMCS is a different job, covered in my WHMCS hooks guide.
What is the WHMCS API, and which form do you need?
The WHMCS API is a set of named actions, such as AddClient or GetInvoices, that let code do what staff do in the admin area. The API index listed 162 actions when I counted them, grouped under headings such as Orders, Billing, Client, Support, Service and Domains. There are two ways to reach them.
- External API. For a system hosted somewhere else: a marketing site, a mobile app backend, an accounting tool. It accepts POST requests at
https://your-whmcs-url/includes/api.php. - Internal API. For code inside the WHMCS installation: hooks, modules and custom pages. It is one PHP function,
localAPI().
Both run the same actions with the same parameters, so the reference page for an action serves both.
How do you create WHMCS API credentials?
You create them at Configuration > System Settings > Manage API Credentials, and you must create an API role first. The role is the list of actions the credential may run. The steps below follow the API Credentials documentation.
- On the API Roles tab, click Create API Role, name it, and tick only the actions this integration needs.
- On the API Credentials tab, click Generate New API Credential.
- Select the admin user the credential will authenticate as, add a description, and select the role.
- Click Generate and copy the identifier and the secret. If you lose the secret, you have to generate a new pair and delete the old one.
Three rules catch people out. The admin user's role group needs the API Access permission. A credential with no role is authorized for nothing. And disabling or deleting the admin user invalidates that user's credentials, while changing the admin's password does not.
The authentication page also describes an older method: an admin username with the MD5 hash of the admin password. It is kept for backwards compatibility and may be deprecated. I do not use it for new work, because it ties an integration to a person's login.
How do you allow your server's IP address to use the WHMCS API?
Add the address under API IP Access Restriction on the Security tab at Configuration > System Settings > General Settings. The access control page states that access to the API is restricted by IP by default, so a correct identifier and secret are not enough on their own. That page still gives the old menu path, "Setup > General Settings > Security".
When the caller has no fixed address, WHMCS offers an access key. Add this line to configuration.php in the WHMCS root, then send the same value as an accesskey parameter with every request:
$api_access_key = 'a-long-random-passphrase';
The key bypasses the IP restriction, so it removes a layer of protection. Use it only when a fixed address is not possible, and treat it like a second secret.
How do you make a first WHMCS API call?
Send a POST with four fields plus the parameters of the action: identifier, secret, action and responsetype. This PHP example looks up a client by email address.
<?php
$keys = require '/home/acme/whmcs-api-keys.php'; // outside the web root
$ch = curl_init('https://billing.example.com/includes/api.php');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query([
'identifier' => $keys['identifier'],
'secret' => $keys['secret'],
'action' => 'GetClientsDetails',
'email' => 'jane@example.com',
'responsetype' => 'json',
]),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$data = json_decode(curl_exec($ch), true);
if (($data['result'] ?? '') !== 'success') {
throw new RuntimeException($data['message'] ?? 'No valid reply from WHMCS');
}
echo $data['client']['fullname'];
Every response carries a result field that is either success or error, and an error comes with a message such as "Client Not Found". The documentation lists three response types: JSON, which it recommends, XML, and NVP, which is deprecated. For a first test, WhmcsDetails needs no parameters and returns the version of the installation.
One detail in that example is easy to miss. GetClientsDetails still returns the client fields at the top level of the response, but the reference marks that copy as deprecated. Read from the client array.
Which WHMCS API actions are used most?
These nine cover most of the integration work I am asked for. The required parameters are in addition to action.
| Action | What it does | Required parameters | Worth knowing |
|---|---|---|---|
WhmcsDetails | Returns the version of the installation. | None. | A safe first test of credentials and IP access. |
AddClient | Adds a client. | Name, email, address, city, state, postcode, country and phone number, plus password2 when no owner_user_id is sent. | Returns clientid. Set noemail to true to skip the welcome email. |
GetClientsDetails | Returns one client's details. | clientid or email. | Add stats for account statistics. |
AddOrder | Adds an order to a client. | clientid and paymentmethod. | It ignores the product's "setup as soon as an order is placed" option, so you must call AcceptOrder afterwards. |
AcceptOrder | Accepts a pending order. | orderid. | autosetup and sendemail control provisioning and emails. |
GetInvoices | Lists invoices. | None. | Filter by userid or status. Returns 25 records unless you set limitnum. |
AddInvoicePayment | Adds a payment to an invoice. | invoiceid, transid, gateway and date. | Leave amount out to pay the full invoice. |
ModuleCreate | Runs the module create action for a service. | serviceid. | Siblings: ModuleSuspend, ModuleUnsuspend, ModuleTerminate. |
CreateSsoToken | Creates a single-use login token for a client or user. | client_id or user_id. | The token is valid for 60 seconds at most. |
ModuleCreate only tells WHMCS to run the provisioning module assigned to the product. What that module does on the remote system is a separate piece of code, which I cover in my guide to building a WHMCS provisioning module.
How do you call the WHMCS API from inside WHMCS with localAPI?
Call localAPI($command, $values, $adminUsername) and read the returned array. The third argument is an admin username, which the WHMCS troubleshooting page marks as optional.
$result = localAPI('GetClientsDetails', ['clientid' => 42, 'stats' => true]);
if ($result['result'] === 'success') {
$email = $result['client']['email'];
}
The internal API page says a hook or module does not need to include init.php, because WHMCS is already running. A standalone PHP script in the WHMCS directory does need require_once 'init.php'; first. No HTTP request is involved.
How do you page through WHMCS API results?
List actions such as GetInvoices take limitstart as the offset and limitnum as the page size, and they report totalresults, startnumber and numreturned. The default is 25 records, so a script that reads only the first response silently misses the rest. Loop until startnumber plus numreturned reaches totalresults, and stop the loop on any response whose result is not success.
How do you debug a WHMCS API call that fails?
Read the message field first, then check the three things that sit in front of every action: the role, the IP address and the credential. If that does not explain it, WHMCS has two logging switches.
- API debug logging. The API troubleshooting page says to add
$api_enable_logging = true;toconfiguration.php. Calls are then written to thetblapilogdatabase table. Remove the line when you finish. - Log API Authentication. This setting on the Security tab of General Settings records successful API authentications in the Admin Log at Configuration > System Logs. It is off by default.
Then cut the request down to the documented example for that action and add your parameters back one at a time. AddOrder rewards that patience, because many of its parameters are arrays with one entry per product.
What are the limits and risks of the WHMCS API?
The main risk is that an API credential does whatever its role allows, with no person watching. Plan for these points.
- Keep roles narrow. A reporting script needs the "Get" actions and nothing else. Give each integration its own credential so you can delete one without breaking the others.
- Never call the API from browser JavaScript. The identifier and secret would be readable by every visitor. Put a small server-side script between the browser and WHMCS.
- Treat
CreateSsoTokenwith care. The reference warns that the token gives complete authentication to the client account and that the login it leads to does not enforce captcha or two-factor checks. Verify the person's identity on your side first. - Do not write to the WHMCS database when an action exists. A direct insert can skip validation and follow-up steps that the action performs.
- The API does not notify you. It answers when asked. To be told that an invoice was paid or a client signed up, use a hook.
If you would rather have an integration built and tested on a staging copy, that is my WHMCS API integration and automation service, and a review of existing credentials and roles is part of a WHMCS security audit; the scoping call of about 30 minutes is free and a written quote follows within one business day.
Last reviewed 10 October 2026. Disclosure: I am a freelance WHMCS developer and I sell API integration work at $55-$65 per hour or a fixed quote, so I am not neutral. I am CTO at ElySpace, a freelance developer for Marmaids LLC, and founder of WHMCSPilot and MagizAI.