Note: The Python examples below now use requests instead of httplib2. By using requests.post() with the necessary authentication, headers, and SSL options, the code is simpler and compatible with modern Python versions (e.g., 3.11). Successful HTTP 200 responses are parsed with getparser() from xmlrpc.client; otherwise, a ProtocolError is raised. This approach streamlines SSL handling, authentication, and header management. Also, requests by default writes more information about its internal work for example, errors or warnings about SSL settings.
* Digest Authentication for Trusted Numbers Manipulation and CLI Mapping
See introduction to XMLAPI for details on Authentication:
https://support.sippysoft.com/a/solutions/articles/106909
#!/usr/bin/env python ## this script requires requests to be installed ## username should be Web Login of the Customer, password - API password ## 1.2.3.4 should be replaced with target IP/hostname of Sippy import requests from requests.auth import HTTPDigestAuth from urllib.parse import urlparse try: from xmlrpc.client import ServerProxy, getparser, ProtocolError except ImportError: from xmlrpclib import ServerProxy, getparser, ProtocolError class HTTPSDigestAuthTransport: def request(self, host, handler, request_body, verbose=0): full_url = f"https://{host}" parsed = urlparse(full_url) username = parsed.username password = parsed.password hostname = parsed.hostname port = parsed.port or 443 url = f"https://{hostname}:{port}{handler}" if verbose: print(f"Making request to: {url}") print(f"Username: {username}, Password: {password}") response = requests.post(url, data=request_body, headers={"content-type": "text/xml"}, auth=HTTPDigestAuth(username, password), verify=True) if response.status_code != 200: raise ProtocolError(url, response.status_code, response.reason, None) p, u = getparser(use_datetime=0) p.feed(response.content) return u.close() if __name__ == "__main__": transport = HTTPSDigestAuthTransport() client = ServerProxy("https://username:[email protected]/xmlapi/xmlapi", transport) ## add a mapping res = client.addCLIMapping({"i_account": 35, "cli": "123456", "lang": "en"}) print(res["result"]) ## retrieve list of trusted numbers res = client.listCLIMappings({"i_account": 35}) if res["result"] == "OK": for cli, lang in res["list"]: print(cli, lang)
* Trusted Authentication for Trusted Numbers Manipulation and CLI Mapping
In this example i_customer should be supplied to selected XMLAPI method, which is mandatory for most methods in trusted mode.
#!/usr/bin/env python ## this script requires requests to be installed ## 1.2.3.4 should be replaced with target IP/hostname of Sippy import requests try: from xmlrpc.client import ServerProxy, getparser, ProtocolError except ImportError: from xmlrpclib import ServerProxy, getparser, ProtocolError class HTTPSTrustedAuthTransport: def request(self, host, handler, request_body, verbose=0): url = f"https://{host}{handler}" if verbose: print(f"Making request to: {url}") response = requests.post(url, data=request_body, headers={"content-type": "text/xml"}, verify=True) if response.status_code != 200: raise ProtocolError(url, response.status_code, response.reason, None) p, u = getparser(0) p.feed(response.content) return u.close() transport = HTTPSTrustedAuthTransport() client = ServerProxy("https://1.2.3.4/xmlapi/xmlapi", transport) ## add a mapping res = client.addCLIMapping({'i_customer': 1, 'i_account': 35, 'cli': '123456', 'lang': 'en'}) print(res['result']) ## retrieve list of trusted numbers res = client.listCLIMappings({'i_customer': 1, 'i_account': 35}) if res['result'] == 'OK': for cli, lang in res['list']: print(cli, lang)
* Manage Call-Back Calls
#!/usr/bin/env python ## this script requires requests to be installed ## 1.2.3.4 should be replaced with target IP/hostname of Sippy import requests from requests.auth import HTTPDigestAuth try: from urllib.parse import urlparse from xmlrpc.client import ServerProxy, getparser, ProtocolError except ImportError: from urlparse import urlparse from xmlrpclib import ServerProxy, getparser, ProtocolError my_number = '12061234567' destination_number = '12067654321' authname = '000125' class HTTPSDigestAuthTransport: def request(self, host, handler, request_body, verbose=0): parsed = urlparse("https://" + host) username = parsed.username password = parsed.password hostname = parsed.hostname port = parsed.port or 443 url = f"https://{hostname}:{port}{handler}" if verbose: print(f"Making request to: {url}") response = requests.post(url, data=request_body, headers={'content-type': 'text/xml'}, auth=HTTPDigestAuth(username, password), verify=True) if response.status_code != 200: raise ProtocolError(url, response.status_code, response.reason, None) p, u = getparser(0) p.feed(response.content) return u.close() transport = HTTPSDigestAuthTransport() client = ServerProxy("https://username:[email protected]/xmlapi/xmlapi", transport) res = client.make2WayCallback({ 'authname' : authname, 'cld_first' : my_number, 'cld_second' : destination_number, 'credit_time': 3600 # call should not continue more than an hour }) if res['result'] == 'OK': print(res['i_callback_request'])
* Refunding an Account
#!/usr/bin/env python ## this script requires requests to be installed ## 1.2.3.4 should be replaced with target IP/hostname of Sippy import requests from requests.auth import HTTPDigestAuth try: from urllib.parse import urlparse from xmlrpc.client import ServerProxy, getparser, ProtocolError except ImportError: from urlparse import urlparse from xmlrpclib import ServerProxy, getparser, ProtocolError class HTTPSDigestAuthTransport: def request(self, host, handler, request_body, verbose=0): parsed = urlparse("https://" + host) username = parsed.username password = parsed.password hostname = parsed.hostname port = parsed.port or 443 url = f"https://{hostname}:{port}{handler}" if verbose: print(f"Making request to: {url}") response = requests.post(url, data=request_body, headers={'content-type': 'text/xml'}, auth=HTTPDigestAuth(username, password), verify=True) if response.status_code != 200: raise ProtocolError(url, response.status_code, response.reason, None) p, u = getparser(0) p.feed(response.content) return u.close() transport = HTTPSDigestAuthTransport() client = ServerProxy("https://username:[email protected]/xmlapi/xmlapi", transport) res = client.accountAddFunds({ 'i_account' : 35, 'amount' : 1.23, 'currency' : 'USD', 'payment_notes' : 'Test credit' }) print(res['result'])
* Python multicall example
https://support.sippysoft.com/a/solutions/articles/3000108533