Skip to content

API overview

FlySIP has an XML-RPC API for everything you do in the panel: customers, accounts, vendors, tariffs, routing, DIDs, payments, CDRs. Use it to provision from your own billing or CRM, to sell from a website, and to pull call records into your reporting. Every call acts on behalf of one customer and sees only what that customer sees in the panel.

API calls are authenticated with the Web Login of a customer and a separate API Password.

  1. Open My Preferences to use the API as yourself, or open the customer under My Customers → Customers to give a reseller access.
  2. Enter an API Password and select Allow API Calls.
  3. Click Save.

The fields are shown only when your login has API management rights. A customer without Allow API Calls gets an authentication error on every call.

https://<your-panel-host>/xmlapi/xmlapi
  • Transport: HTTPS POST with Content-Type: text/xml.
  • Authentication: HTTP Digest. The user name is the customer’s Web Login, the password is the API Password. Basic authentication is not accepted.
  • Scope: the authenticated customer. Methods reach its own objects and its sub-customers; objects of other customers are reported as not found.

Test the credentials with curl. A working call returns up to five of your accounts:

Terminal window
curl --digest -u acme-web:API-PASSWORD -H 'Content-Type: text/xml' \
--data '<?xml version="1.0"?><methodCall><methodName>listAccounts</methodName><params><param><value><struct><member><name>limit</name><value><int>5</int></value></member></struct></value></param></params></methodCall>' \
https://panel.example.com/xmlapi/xmlapi

Calls from the switch itself and from hosts the switch trusts are accepted without digest authentication. Such a call does not identify a customer, so methods that support trusted mode take an extra parameter that names the customer to act for, usually i_customer and for some methods i_wholesaler. The method pages mention it where it applies. External integrations always use digest authentication and never need these parameters.

Every method takes exactly one parameter, a struct, and returns a struct. Parameter names are case-sensitive and use snake_case; internal IDs start with i_, for example i_account, i_customer, i_tariff. Most methods also accept l10n_lang, a two-letter language code such as en or ru, which sets the language of fault messages.

<?xml version="1.0"?>
<methodCall>
<methodName>getAccountInfo</methodName>
<params>
<param>
<value>
<struct>
<member>
<name>i_account</name>
<value><int>3092</int></value>
</member>
</struct>
</value>
</param>
</params>
</methodCall>

An array parameter is a list of values inside <array><data>:

<member>
<name>target_hosts</name>
<value><array><data>
<value><string>192.0.2.10</string></value>
<value><string>192.0.2.11</string></value>
</data></array></value>
</member>

To send several calls in one HTTP request, use system.multicall. See Batch calls with multicall.

A successful call returns a struct with result set to OK and the method’s own members. A few methods differ: some report status instead of result, and some return their data without either; their pages say so. A typical response:

<?xml version="1.0"?>
<methodResponse>
<params>
<param>
<value>
<struct>
<member><name>result</name><value><string>OK</string></value></member>
<member><name>i_account</name><value><int>3092</int></value></member>
</struct>
</value>
</param>
</params>
</methodResponse>

Empty values can be returned as <nil/>. Make sure your client library accepts it: in Apache XML-RPC for Java, call setEnabledForExtensions(true) on the client configuration.

A failed call returns an XML-RPC fault instead of a result. faultString is a readable message for the log; faultCode tells you the class of the problem.

<?xml version="1.0"?>
<methodResponse>
<fault>
<value>
<struct>
<member><name>faultCode</name><value><int>401</int></value></member>
<member><name>faultString</name><value><string>Wrong i_tariff</string></value></member>
</struct>
</value>
</fault>
</methodResponse>
faultCode Meaning
400 A required parameter is missing, parameters conflict, or the object cannot be changed in this way
401 A parameter has a wrong value, the customer is not allowed to call the method, or the object was not found
402 Bad input: a missing field, an unknown value, a malformed date
403, 404 The object does not exist or belongs to another customer
408 The operation timed out on the switch
410 A required parameter is missing in some methods, or the service is temporarily unavailable; the method page says which
500 Internal error; retry later and report it if it persists

Codes are not unique per error and older methods often use 401 for “not found”, so log faultString and do not branch on fine differences between codes. An HTTP 401 response, not a fault, means the digest credentials were rejected.

XML-RPC type Used for
int IDs (i_*), counters, enumerations
double Money and rates, for example balance, credit_limit, price_1
string Names, numbers, passwords, regular expressions
boolean Flags. Many older methods also accept int 0 / 1 for flags
dateTime.iso8601 Dates and times, always in UTC, without a time zone: 20260115T13:30:00
array, struct Lists and nested objects
base64 Binary data, for example a call recording

Country codes are ISO 3166 (TR or TUR), currency codes are ISO 4217 (USD, EUR, TRY). Balances are in the customer’s or account’s currency.

The standard xmlrpc.client module has no digest authentication, so the examples on these pages use this helper built on requests:

flysip_api.py
import xmlrpc.client
import requests
from requests.auth import HTTPDigestAuth
URL = "https://panel.example.com/xmlapi/xmlapi"
AUTH = HTTPDigestAuth("acme-web", "API-PASSWORD")
def call(method: str, params: dict) -> dict:
"""Call one API method; raises xmlrpc.client.Fault on a fault."""
body = xmlrpc.client.dumps((params,), method, allow_none=True)
resp = requests.post(URL, data=body.encode(), auth=AUTH,
headers={"Content-Type": "text/xml"}, timeout=30)
resp.raise_for_status()
return xmlrpc.client.loads(resp.content, use_builtin_types=True)[0][0]
print(call("getAccountInfo", {"username": "1001"}))

xmlrpc.client sends Python int, float, str, bool, datetime, list and dict as the matching XML-RPC types. When the panel has a self-signed certificate, pass its CA file to requests.post(..., verify="flysip-ca.pem") instead of turning verification off. A longer example is in Python client.

Group What you manage
Accounts Accounts and their authentication rules, trusted numbers, follow-me, hot dial, smart dial, trunks, incoming routes
Customers Customers and resellers, their login and blocking
Vendors Vendors, their connections and balances
Tariffs Tariffs and their rates
CDRs Call records of accounts, customers and vendors, call search with diagnosis, call recordings
Reports Summary reports by account, customer, vendor and DID, and pre-aggregated statistics
Payments Payments, refunds, vouchers, stored cards, low-balance warnings
Environments Environments of a multi-tenant switch
Other methods DIDs, destination sets, routing groups, IVR, active calls, certificates, firewall rules, password policies, system settings

Bulk uploads of rates and routes use binary upload. For simple HTTP GET integrations without XML-RPC, see Simple API.