Remote API and issues with "invalid client_id"

Discussion in 'General' started by Medium Buddha, Nov 29, 2025.

  1. Medium Buddha

    Medium Buddha New Member

    Hello,
    I am creating a new client via remote api. I can see this client in isponfig.
    But when I try to add a web domain via remote api, I have the issue that it doesn't work, the error is "SOAP Fault: Invalid client_id xxx".
    I can add a webdomain manually to this client or I can add via remote api a webdomain without client association an set it later in the frontend.
    Just via remote api, I have this issue.
    I am wondering how I can check what is wrong?
    The ispconfig installation is running the current version.

    Code to add a client:
    Code:
    <?php
    $soapLocation = 'https://sub.domain.net/remote/index.php';
    $soapUri = 'https://sub.domain.net/remote/';
    $soapUsername = 'remote_api_user';
    $soapPassword = 'password';
    $resellerId = 0;
    $defaultWebserverId = 1;
    $defaultDbServerId = 1;
    $defaultDnsServerId = 1;
    
    $client = new SoapClient(null, [
    'location' => $soapLocation,
    'uri' => $soapUri,
    'trace' => 1,
    'exceptions' => true,
    'stream_context' => stream_context_create([
    'ssl' => [
    'verify_peer' => false,
    'verify_peer_name' => false,
    'allow_self_signed' => true,
    ],
    ]),
    ]);
    
    $session = $client->login($soapUsername, $soapPassword);
    
    $companyName = 'API Testkunde ' . date('Ymd-His');
    $username = strtolower(preg_replace('~[^a-zA-Z0-9]~', '', substr($companyName, 0, 10))) . rand(100, 999);
    $password = bin2hex(random_bytes(8));
    
    $params = [
    'company_name' => $companyName,
    'contact_name' => 'API Test',
    'customer_no' => 'T' . rand(1000, 9999),
    'vat_id' => '',
    'street' => 'Teststraße 1',
    'zip' => '12345',
    'city' => 'Teststadt',
    'state' => '',
    'country' => 'DE',
    'telephone' => '',
    'mobile' => '',
    'fax' => '',
    'email' => '[email protected]',
    'internet' => '',
    'icq' => '',
    'notes' => 'Created via client_add.php',
    
    'default_mailserver' => 1,
    'limit_maildomain' => -1,
    'limit_mailbox' => -1,
    'limit_mailalias' => -1,
    'limit_mailaliasdomain' => -1,
    'limit_mailforward' => -1,
    'limit_mailcatchall' => -1,
    'limit_mailrouting' => 0,
    'limit_mailfilter' => -1,
    'limit_fetchmail' => -1,
    'limit_mailquota' => -1,
    'limit_spamfilter_wblist' => 0,
    'limit_spamfilter_user' => 0,
    'limit_spamfilter_policy' => 1,
    
    'default_webserver' => $defaultWebserverId,
    'web_servers' => (string)$defaultWebserverId,
    'limit_web_ip' => '',
    'limit_web_domain' => -1,
    'limit_web_quota' => -1,
    'web_php_options' => 'no,fast-cgi,cgi,mod,suphp,php-fpm',
    'limit_web_subdomain' => -1,
    'limit_web_aliasdomain' => -1,
    'limit_ftp_user' => -1,
    'limit_shell_user' => 0,
    'ssh_chroot' => 'no,jailkit,ssh-chroot',
    'limit_webdav_user' => 0,
    
    'default_dnsserver' => $defaultDnsServerId,
    'dns_servers' => (string)$defaultDnsServerId,
    'limit_dns_zone' => -1,
    'limit_dns_slave_zone' => -1,
    'limit_dns_record' => -1,
    
    'default_dbserver' => $defaultDbServerId,
    'db_servers' => (string)$defaultDbServerId,
    'limit_database' => -1,
    
    'limit_cron' => 0,
    'limit_cron_type' => 'url',
    'limit_cron_frequency' => 5,
    'limit_traffic_quota' => -1,
    'limit_client' => 0,
    
    'username' => $username,
    'password' => $password,
    'language' => 'de',
    'usertheme'=> 'default',
    ];
    
    try {
    $clientId = $client->client_add($session, $resellerId, $params);
    echo "Client erfolgreich angelegt.\n";
    echo "Client-ID: {$clientId}\n";
    echo "Username : {$username}\n";
    echo "Password : {$password}\n";
    } catch (SoapFault $e) {
    echo "SOAP Fault: {$e->getMessage()}\n";
    echo "Last Request:\n" . $client->__getLastRequest() . "\n";
    echo "Last Response:\n" . $client->__getLastResponse() . "\n";
    }
    $client->logout($session);
    
    
    What I just found out. I cannot log in as a user (from the admin panel admin) with these "invalid clients"... the error shown is: "The password length is < 1 or > 256 characters."

    When I try to login with the just created credentials I have an error: "Username or Password wrong."

    > php test_client_add.php
    Client erfolgreich angelegt.
    Client-ID: 1234
    Username : apitestku321
    Password : 353b29f6bae8c030

    I have the same issue with using the example script from here:
    https:// git.ispconfig.org/ispconfig/ispconfig3/-/blob/develop/remoting_client/examples/client_add.php

    Same issue with REST Api with endpoint https:// sub.domain.net/remote/json.php
    ...
    Any help apreciated.
     
    Last edited: Dec 1, 2025
  2. pyte

    pyte Well-Known Member HowtoForge Supporter

    I don't know what the issue here is. This works for us:

    PHP:
     $customer = array("company_name" => "TestCompany",
                        
    "customer_no" => 101010,
                        
    "contact_name" => "Lastname",
                        
    "contact_firstname" => "Firstname",
                        
    "telephone" => "01234567",
                        
    "street" => "Road",
                        
    "zip" => "102030",
                        
    "city" => "Neverland",
                        
    "country" => "DE",
                        
    "fax" => "012345",
                        
    "email" => "[email protected]",
                        
    "internet" => "company.com",
                        
    "limit_client" => 0,
                        
    "parent_client_id" => 0,
                        
    "username" => "101010",
                        
    "password" => '',
                        
    "language" => 'de',
                        
    "usertheme" => 'default',
                        
    "template_master" => 1,
                        
    "created_at" => 0,
                        
    "default_mailserver" => 0,
                        
    "mail_servers" => 7,
                        
    "limit_maildomain" => 50,
                        
    "limit_mailbox" => 100,
                        
    "limit_mailalias" => -1,
                        
    "limit_mailaliasdomain" => -1,
                        
    "limit_mailforward" => -1,
                        
    "limit_mailcatchall" => -1,
                        
    "limit_mailrouting" => -1,
                        
    "limit_mail_wblist" => -1,
                        
    "limit_mailfilter" => -1,
                        
    "limit_fetchmail" => -1,
                        
    "limit_mailquota" => 10240,
                        
    "limit_spamfilter_wblist" => -1,
                        
    "limit_spamfilter_user" => -1,
                        
    "limit_spamfilter_policy" => -1,
                        
    "limit_mail_backup" => 'y',
                        
    "limit_relayhost" => 'n',
                        
    "default_webserver" => 0,
                        
    "limit_web_domain" => 100,
                        
    "limit_web_quota" => 10240,
                        
    "web_php_options" => 'fast-cgi,mod,php-fpm',
                        
    "limit_cgi" => 'n',
                        
    "limit_ssi" => 'n',
                        
    "limit_perl" => 'n',
                        
    "limit_ruby" => 'n',
                        
    "limit_python" => 'n',
                        
    "force_suexec" => 'y',
                        
    "limit_hterror" => 'y',
                        
    "limit_wildcard" => 'n',
                        
    "limit_ssl" => 'y',
                        
    "limit_ssl_letsencrypt" => 'n',
                        
    "limit_web_subdomain" => -1,
                        
    "limit_web_aliasdomain" => -1,
                        
    "limit_ftp_user" => 10,
                        
    "limit_shell_user" => 0,
                        
    "ssh_chroot" => 'jailkit',
                        
    "limit_webdav_user" => 0,
                        
    "limit_backup" => 'n',
                        
    "limit_directive_snippets" => 'n',
                        
    "limit_aps" => 0,
                        
    "default_dnsserver" => 0,
                        
    "db_servers" => 5,
                        
    "limit_dns_zone" => 0,
                        
    "default_slave_dnsserver" => 6,
                        
    "limit_dns_slave_zone" => 0,
                        
    "limit_dns_record" => -1,
                        
    "default_dbserver" => 0,
                        
    "dns_servers" => 6,
                        
    "limit_database" => 10,
                        
    "limit_database_user" => -1,
                        
    "limit_database_quota" => 10240,
                        
    "limit_cron" => 0,
                        
    "limit_cron_type" => 'url',
                        
    "limit_cron_frequency" => 5
                        
    );

    $rand_pw gen_randpw();
    $customer['password'] = $rand_pw;
    $soapClient->client_add($sessionId0$customer);
    You need to change the mail_servers, db_servers and dns_servers with the correct IDs of your servers.
     
    till likes this.
  3. Medium Buddha

    Medium Buddha New Member

    Hi pyte,
    Thank you for your message.
    I ma trying to find out what could be different on your setup..
    Do you also run a mutliserver environment?
    As I mentioned: I can create clients, be somehow they seem to be broken: I cannot log in to ispconfig with the client usernames and I cannot create sites via remote (with $client->sites_web_domain_add($session, $clientId, $params)). I get a soap error "Invalid client_id".
    The strange thing is that I can add a site for the client I added via remote when I am logged in as admin. So the issue is somehow bound to remote api.

    Best regards
     
  4. Medium Buddha

    Medium Buddha New Member

    OK, I think I know what is wrong, ewvev thoug, I don't know why.
    Creating a client with the remote api, creates a client in the client table in the database, but there is no entry in the sys_user and sys_group tables...
    Need to investigate...

    UPDATE: I didn't check well, sys_group entry is made. Solely sys_user isn't set.
     
    Last edited: Dec 5, 2025 at 5:51 PM
  5. variable99

    variable99 Active Member HowtoForge Supporter

    Hey Buddha.

    Here is ISPC API wrapper I extended and updated from somewhere. It works something like this (you need to adapt):

    PHP:
    // server prepare for API interaction
        
    public function prepareServer()
        {
            
    // get main panel server data
            
    $server = new \Models\Servers();
            
    $server->load(['ispc_server_id = ?'1]);

            if (
    $server->dry()) {
                return 
    false;
            }

            return new \
    Helpers\ISPConfig3(
                [
                    
    'host' => 'https://' $server->hostname ':' $server->port,
                    
    'user' => $server->api_user,
                    
    'pass' => $server->api_password
                
    ]
            );
        }

    // create user
                
    $user $this->panelServer
                    
    ->with(
                        [
                            
    'contact_name' => 'name',
                            
    'username' => 'username',
                            
    'password' => 'password',
                            
    'email' => '[email protected]',
                            
    'language' => '',
                            
    'usertheme' => 'default',
                            
    'country' => 'EN',
                            
    'template_master' => 1,
                            
    'created_at' => 0,
                            
    'notes' => "notes",
                            
    'web_php_options' => 'no,php-fpm',
                            
    'ssh_chroot' => 'no,jailkit',
                            
    'limit_cron_type' => 'chrooted',
                            
    'added_by' => 'api',
                        ]
                    )
                    ->
    addClient()
                    ->
    response();

                
    $ISPC_user json_decode($usertrue);

                if (!isset(
    $ISPC_user['result'])) {
                    echo 
    $this->log->log('Failed to add user: ' $usernamenullnull$ISPC_user['error']['message'] ? $ISPC_user['error']['message'] : $user);
                }
    Enjoy.
    P.s. I have added few extra API endpoints for information extraction in the way I like, so some rare wrapper functions may not work for you. But 97% will work as it should. PHP8+ supported.
     

    Attached Files:

  6. till

    till Super Moderator Staff Member ISPConfig Developer

    Either the username is invalid, the password is empty or the username exists already.
     
  7. Medium Buddha

    Medium Buddha New Member

    Here is the current version of the script:

    Code:
    <?php
    require_once __DIR__ . '/src/RandomGenerator.php';
    $config = require __DIR__ . '/config.php';
    $isp = $config['ispconfig'];
    
    $client = new SoapClient(null, [
    'location' => $isp['soap_location'],
    'uri' => $isp['soap_uri'],
    'trace' => 1,
    'exceptions' => true,
    'stream_context' => stream_context_create([
    'ssl' => [
    'verify_peer' => false,
    'verify_peer_name' => false,
    'allow_self_signed' => true,
    ],
    ]),
    ]);
    
    try {
    $session_id = $client->login($isp['username'], $isp['password']);
    echo "✅ Login erfolgreich. Session ID: {$session_id}\n\n";
    
    // Eindeutigen Username generieren
    $timestamp = time();
    $suffix = random_int(1000, 9999);
    $username = 'testclient_' . $suffix;
    $password = RandomGenerator::password(16);
    
    echo "Client-Daten:\n";
    echo " Username: {$username}\n";
    echo " Password: {$password}\n\n";
    
    // Server-IDs aus Config
    $webServerId = $isp['default_webserver_id'] ?? 1;
    $dbServerId = $isp['default_dbserver_id'] ?? 1;
    $dnsServerId = $isp['default_dnsserver_id'] ?? 1;
    
    $reseller_id = 0; // 0 = Admin (kein Reseller als Parent)
    
    $params = [
    // === KONTAKTDATEN ===
    'company_name' => 'Test Company ' . $suffix,
    'contact_name' => 'Max Mustermann',
    'contact_firstname' => 'Max',
    'customer_no' => 'CUST-' . $suffix,
    'vat_id' => '',
    'street' => 'Teststraße 123',
    'zip' => '12345',
    'city' => 'Berlin',
    'state' => 'Berlin',
    'country' => 'DE',
    'telephone' => '+49 30 12345678',
    'mobile' => '',
    'fax' => '',
    'email' => 'test' . $suffix . '@example.com',
    'internet' => 'https://example.com',
    'notes' => 'Automatisch angelegt per Remote API',
    
    // === MAIL-LIMITS ===
    'limit_maildomain' => -1, // -1 = unbegrenzt, 0 = deaktiviert, >0 = Anzahl
    'limit_mailbox' => -1,
    'limit_mailalias' => -1,
    'limit_mailaliasdomain' => -1,
    'limit_mailforward' => -1,
    'limit_mailcatchall' => -1,
    'limit_mailrouting' => 0,
    'limit_mailfilter' => -1,
    'limit_fetchmail' => -1,
    'limit_mailquota' => -1, // MB
    'limit_spamfilter_wblist' => 0,
    'limit_spamfilter_user' => 0,
    'limit_spamfilter_policy' => 1,
    
    // === WEB-LIMITS ===
    'default_webserver' => $webServerId,
    'web_servers' => (string)$webServerId,
    'limit_web_ip' => '', // Leer = keine IP-Beschränkung
    'limit_web_domain' => -1, // Anzahl Domains
    'limit_web_quota' => -1, // MB Speicherplatz (-1 = unbegrenzt)
    'limit_web_subdomain' => -1,
    'limit_web_aliasdomain' => -1,
    'limit_ftp_user' => -1,
    'limit_shell_user' => 0, // 0 = kein Shell-Zugriff
    'limit_webdav_user' => 0,
    
    'web_php_options' => 'no,fast-cgi,cgi,mod,suphp,php-fpm',
    
    // SSH Chroot-Optionen
    'ssh_chroot' => 'no,jailkit,ssh-chroot',
    
    // === DNS-LIMITS ===
    'default_dnsserver' => $dnsServerId,
    'dns_servers' => (string)$dnsServerId,
    'limit_dns_zone' => -1,
    'limit_dns_slave_zone' => -1,
    'limit_dns_record' => -1,
    
    // === DATENBANK-LIMITS ===
    'default_dbserver' => $dbServerId,
    'db_servers' => (string)$dbServerId,
    'limit_database' => -1,
    
    // === WEITERE LIMITS ===
    'limit_cron' => 0, // Anzahl Cron-Jobs
    'limit_cron_type' => 'url',
    'limit_cron_frequency' => 5, // Minuten zwischen Ausführungen
    'limit_traffic_quota' => -1, // MB Traffic
    
    // === CLIENT-TYP ===
    'limit_client' => 0, // 0 = normaler Client, >0 = Reseller mit X Sub-Clients
    'parent_client_id' => 0, // 0 = kein Parent (direkt unter Admin)
    
    // === LOGIN-DATEN ===
    'username' => $username,
    'password' => $password,
    'language' => 'de',
    'usertheme' => 'default',
    
    // === TEMPLATES ===
    'template_master' => 0, // 0 = kein Master-Template
    'template_additional' => '', // Zusätzliche Templates (durch / getrennt)
    
    'created_at' => $timestamp,
    ];
    
    echo "Client wird angelegt...\n";
    $client_id = $client->client_add($session_id, $reseller_id, $params);
    
    if (is_numeric($client_id) && $client_id > 0) {
    echo "✅ Client erfolgreich angelegt!\n";
    echo " Client-ID: {$client_id}\n\n";
    
    echo "Prüfe angelegten Client...\n";
    $client_data = $client->client_get($session_id, (int)$client_id);
    
    if ($client_data && isset($client_data['client_id'])) {
    echo "✅ Client gefunden und lesbar:\n";
    echo " Company: " . ($client_data['company_name'] ?? 'N/A') . "\n";
    echo " Username: " . ($client_data['username'] ?? 'N/A') . "\n";
    echo " Email: " . ($client_data['email'] ?? 'N/A') . "\n";
    echo " Web Domains Limit: " . ($client_data['limit_web_domain'] ?? 'N/A') . "\n";
    echo " Database Limit: " . ($client_data['limit_database'] ?? 'N/A') . "\n";
    echo "\n";
    
    // Speichere die Daten für weitere Tests
    file_put_contents(
    __DIR__ . '/test_client_' . $client_id . '.txt',
    "Client-ID: {$client_id}\n" .
    "Username: {$username}\n" .
    "Password: {$password}\n" .
    "Created: " . date('Y-m-d H:i:s', $timestamp) . "\n"
    );
    echo "ℹ️ Client-Daten gespeichert in: test_client_{$client_id}.txt\n";
    } else {
    echo "⚠️ Client wurde angelegt, aber konnte nicht gelesen werden!\n";
    }
    } else {
    echo "❌ Fehler beim Anlegen des Clients. Rückgabewert: " . var_export($client_id, true) . "\n";
    }
    
    $client->logout($session_id);
    echo "\n✅ Logout erfolgreich.\n";
    
    } catch (SoapFault $e) {
    echo "\n❌ SOAP Fehler: " . $e->getMessage() . "\n\n";
    echo "--- Last Request ---\n";
    echo $client->__getLastRequest() . "\n\n";
    echo "--- Last Response ---\n";
    echo $client->__getLastResponse() . "\n";
    exit(1);
    }
    
    
    
    Here the saved data from the client creation:

    Client-ID: 387
    Username: testclient_8407 (is unique, I have no other client with a username starting with testclient..)
    Password: IW7XMM5RzvVnxDmp (not empty and good enough)
    Created: 2025-12-05 12:13:49

    As I mentioned, the new client shows up in the client list, but has no db entry in the sys_user (sys_group entry is made), and I guess this is the problem...

    UPDATE: I have added manually a sys_user entry and it looks it works.. now I need to find out why these entries are not set by the remote client client_add function..
     
    Last edited: Dec 5, 2025 at 5:50 PM
  8. Medium Buddha

    Medium Buddha New Member

    So, it looks like I have the answer..
    groups is a reserved word and since mysql 8, needs to be set in backsticks.

    Code:
    function ispconfig_sysuser_add($params, $insert_id){
    ...
    $sql1 = "INSERT INTO sys_user (username,passwort,modules,startmodule,app_theme,typ,active,language,`groups`,default_group,client_id)
                            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; 
    instead of
    Code:
    $sql1 = "INSERT INTO sys_user (username,passwort,modules,startmodule,app_theme,typ,active,language,groups,default_group,client_id)
                            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
    Probably there are other queries to update..
     
    till likes this.
  9. till

    till Super Moderator Staff Member ISPConfig Developer

    Thanks, we will fix it with the next release. Some of the older ISPConfig code still has no backticks and as ISPConfig setups are typically based on MariaDB and not MySQL, nobody noticed that yet.
     
    pyte likes this.
  10. till

    till Super Moderator Staff Member ISPConfig Developer

  11. Medium Buddha

    Medium Buddha New Member

    Thank you for your quick response
     
    pyte likes this.

Share This Page