Software API

All functionality of the Spam Experts Local Cloud setup is exposed via the API. A full help listing all available commands can be accessed from the Control Panel by going to Server > Software API Calls or via the api_help call using the following URL:


The API is accessible via HTTPS and can be accessed using simple URL calls. For example, from PHP this can be done using libcurl, it’s also to execute a call from any browser. The commands executed on the Software API are automatically executed on all relevant servers in your Local Cloud setup, so there is no need for you to individually configure the servers. These commands should not be executed from the SSH command line on the SpamExperts system, they can be ran from any external location.

Be advised that the API described on this page (Software API) is only available on our Local Cloud product. For the Hosted Cloud/Control Panel API please refer to the Control Panel API documentation.

Example calls

To add a domain to the filtering cluster, you can simply execute the add_incoming_domain() from a web browser, or directly from a script:


As it can be seen it’s very easy to integrate the adding/removing of domains (and all other available features) in any existing provisioning system or control panel.

Default settings

As Local Cloud administrator you can control the default settings for all domains.

To modify the default domain settings, simply specify “default” as domain.. If the default value is changed, then it will affect any domains that are still set to using the default values. If a custom value has been previously set for a domain, then that will override the default, even if the custom value is the same as the default. To change a domain setting back to use the default value, the special value ‘default’ should be used as argument.

Mind the difference between Domain Default and Value Default. Domain Default changes the setting for all domains using the default values, whereas Value Default changes the setting for a specific domain back to use the “default value”.

When retrieving from the API the value of a setting that has been changed and it’s not default, a warning will be printed to indicate that the setting value is not the default one. The warning will also include the default value for that setting. This allows the caller to distinguish between "use the default" and the same value as the default.

Sample PHP script

'verify_peer' => false,
'verify_peer_name' => false
// end of removal
if (!empty($_REQUEST['action'])) {
switch ($_REQUEST['action']) {
case 'add':
if (!empty($_REQUEST['domain']) && !empty($_REQUEST['destination'])) {

case 'remove':
if (!empty($_REQUEST['domain'])) {

header('Location: '.$_SERVER['PHP_SELF']);

// Getting domains list
$domains = array();
$domains_string = file_get_contents('https://'.LOGIN.'@'.SERVER.'/cgi-bin/api?call=api_list_domains');

$lines = array_filter(explode("\n", $domains_string));
foreach ($lines as $line) {
list($domain, $route_string) = explode(':', $line, 2);

if ('*' == substr($domain, -1)) {
$lastDomain = key($domains);

if (empty($domains[$lastDomain]['aliases'])) {
$domains[$lastDomain]['aliases'] = array();

$domains[$lastDomain]['aliases'][] = rtrim($domain, '*');


$routes = array_filter(explode(',', $route_string));
foreach ($routes as $r => $destination) {
$domains[$domain]['routes'][$r] = str_replace('::', ':', $destination);

Add new domain

View existing domains

$domainRelatedItems) : ?>

Domain Aliases Routes Action
', $domainRelatedItems['aliases']) : ' '); ?> ', $domainRelatedItems['routes']) : ' '); ?> remove
No domains are setup

Sample Python script

DATA HOSTED BY PASTEBIN.COM - Download raw - See original

import os
import json

import requests

import flask

APP = flask.Flask(__name__)
APP.secret_key = "some_secret"

TEMPLATE = """<html><body>
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
<ul class=flashes>
{% for category, message in messages %}
<li class="{{ category }}">{{ message }}</li>
{% endfor %}
{% endif %}
{% endwith %}

<form method="post" action="">
<legend><strong>Add new domain</strong></legend>
<input name="action" type="hidden" value="add" />
<label style="float:left;width:100px;text-align:right;">Domain: </label><input name="domain" type="text" /><br />
<label style="float:left;width:100px;text-align:right;">Route: </label><input name="destination" type="text" /><br />
<input style="margin-left:100px;" type="submit" value="Add" />

<h3>View existing domains</h3>

<table border="1" cellspacing="0" cellpadding="2">
{% if domains %}
{% for info in domains %}
<td>{{ info.domain }}</td>
<td>{{ info.aliases|join('<br />') }}
<td>{{ info.destinations|join('<br />') }}
<td><form method="post" action=""><input name="action" type="hidden" value="remove" /><input name="domain" type="hidden" value="{{ info.domain }}" /><input type="submit" value="remove" /></form></td>
{% endfor %}
{% else %}
<td colspan="4">No domains are set up.</td>
{% endif %}

@APP.route("/", methods=['GET', 'POST'])
def view():
auth = (os.environ["USER"], os.environ["PASSWORD"])
base = "https://%(server)s/cgi-bin/api?call=" % {"server":
if flask.request.method == "POST":
action = flask.request.form["action"]
domain = flask.request.form["domain"]
if (action == "add" and domain and flask.request.form["destination"]):
destinations = []
for destination in flask.request.form["destination"].split(","):
if ":" in destination else
(destination, 25))
data = json.dumps({domain: {"destinations": destinations}})
response = requests.get("%(base)sapi_add_delivery_domain&"
"data=%(data)s" %
{"base": base, "data": data}, auth=auth)
if response.ok:
flask.flash("Added %(domain)s" % {"domain": domain}, "info")
flask.flash("An error occurred.", "error")
elif action == "remove" and domain:
response = requests.get("%(base)sapi_remove_domain&"
"domain=%(domain)s" %
{"base": base, "domain": domain},
if response.ok:
flask.flash("Removed %(domain)s" % {"domain": domain}, "info")
flask.flash("An error occurred.", "error")
return flask.redirect(flask.url_for("view"))
domains = requests.get("%(base)sapi_list_domains&format=json" %
{"base": base}, auth=auth).json()
return flask.render_template_string(TEMPLATE, domains=domains)

Disclaimer: This documentation may contain references to third party software or websites. N-able has no control over third party software or content and is not responsible for the availability, security, or operation, of any third-party software. If you decide to utilize a release involving third-party software, you do so entirely at your own risk and subject to the applicable third party’s terms and conditions of the use of such software. No information obtained by you from N-able or this documentation shall create any warranty for such software.