Custom integration
Custom integration and generic mode
BlissRADIUS Embedded can be integrated with your own built billing software by using generic mode that comes with program. Process is straight forward and method of interaction is same as with WHMCS, Blesta or any other billing software. Once customization is done, installation procedure is not different from any other host type.
Customization, in its simplest form, requires from your software to have HTTP receiver (web page) for all API requests coming from BlissRADIUS Embedded. This can be done as easily as adding one PHP script to web server that is running your billing software. Your software must periodically call BlissRADIUS Embedded API to notify it when certain events occur, and to fetch pieces of HTML code that are injected into your billing web pages.
Example
This example assumes your billing software is Linux or Windows based PHP/MySQL/Apache solution served as a local web site at http://localhost/my_billing
.
BlissRADIUS Embedded is installed and you are using web browser on/from the same computer.
Handling incoming requests
First thing you need is to add script to your software that will be called by BlissRADIUS Embedded
when it needs to fetch service data or send email via your software.
Create PHP file that will be accessible at URL http://localhost/my_billing/api.php
and save contents below:
<?php
// All API responses are JSON encoded dictionary to UTF-8 text. See example below.
// Optional IP address check, you might want to restrict who can call API. This permits only localhost.
// Note: if there is proxy or NAT involved, REMOTE_ADDR will not always return correct address of client.
$remote_addr = $_SERVER["REMOTE_ADDR"];
if ($remote_addr != "127.0.0.1" && $remote_addr != "::1") {
echo json_encode(array("Result" => "error", "Message" => "access denied to ".$remote_addr));
return;
}
// API username/password check, if credentials do not match then reject call.
// This permits only blissembed as default username and password.
// It demonstrates how digest is created from salt, username and password using MD5 algorithm.
// BlissRADIUS Embedded sends api_username, api_salt and api_digest with every API request.
const USERNAME = "blissembed";
const PASSWORD = "blissembed";
$api_username = @$_REQUEST["api_username"];
$api_salt = @$_REQUEST["api_salt"];
$api_digest = @$_REQUEST["api_digest"];
if ($api_username != USERNAME || md5($api_salt.":".$api_username.":".PASSWORD) != $api_digest){
echo json_encode(array("Result" => "error", "Message" => "wrong credentials for ".$api_username));
return;
}
// Two API actions are handled, get_service and send_email. api_action parameter contains desired action.
// Each action comes with own set of additional parameters and returns own response.
$api_action = @$_REQUEST["api_action"];
if ($api_action != "send_email" && $api_action != "get_service"){
echo json_encode(array("Result" => "error", "Message" => "unsupported action ".$api_action));
return;
}
// Handle action send_email. This is used when BlissRADIUS Embedded is configured to send email via host API.
if ($api_action == "send_email"){
// Additional paremeters provided by this action
$address = @$_REQUEST["address"];
$subject = @$_REQUEST["subject"];
$text = @$_REQUEST["text"];
$service_id = @$_REQUEST["service_id"];
$client_id = @$_REQUEST["client_id"];
// Send email, but first check for correctness of address, service_id and client_id.
// There are no guarantees address will be valid, or that service_id or client_id point to existing entities.
// Confirm success
echo json_encode(array("Result" => "success", "Message" => ""));
return;
}
// Handle action get_service
// Provided are either one of these parameters: id for exact match, or username for service username lookup.
// Lookup by id is simple and quick operation if you use primary keys of database.
// Username lookup must be case insensitive. Newer/active services should take precedence if there are multiple services with same username.
$service_id = @$_REQUEST["id"];
$service_username = @$_REQUEST["username"];
// For this example, both parameters are ignored and same test service is always returned.
// It is completely up to you to organize service/product/client/topup data as you desire and extract data from it into meaningful service details.
// Only thing important is that returned response must contain these fields.
$response = array(
"Result" => "success", // "success" or "error", error is set only if there is some kind of programming/database error
"Message" => "", // description of error that prevented API call
"Found" => true, // if service is not found this must be set to false along with "Result" => "success"
"Service" => array( // not present if service is not found
"Id" => 1, // integer ID of service
"Enabled" => true, // true or false if disabled/expired/suspended etc.
"Created" => "2001-01-01T23:00:00+01:00", // ISO 8601 date format, use PHP date() function with "c" format if needed
"Username" => "test", // lower case username
"Password" => "test123", // plain text password, RADIUS authentication methods can't work with password hashes
"Options" => "Permanent = no \n Duration months = 1000 \n GB limit = 10.0 \n Session attributes = Mikrotik-Rate-Limit=512k/5M", // aggregate of product + service options, product options first, separated by newline
"Client" => "John Doe", // human readable client name (first, last name, organization etc.)
"Email" => "john@example.com, john2@test.com", // comma separated list of email addresses that receive notifications
"Phone" => "123456789", // comma separated list of mobile phone number that receive SMS notifications
"Product" => "Test product 10Gbs", // human readable product name
"ProductId" => 123, // integer ID of product
"ClientId" => 221, // integer ID of client
"Topups" => array( // array of all topups for service
array(
"Created" => date("c", strtotime("now")), // ISO 8601 date format, affects topup application (expired, not activated yet etc.)
"Enabled" => true, // true or false if disabled/suspended
"Option" => "GB limit", // canonical option name
"Amount" => 100.0, // amount as floating point number
),
array(
"Created" => date("c", strtotime("now")),
"Enabled" => false,
"Option" => "GB limit",
"Amount" => 50.0,
),
),
),
"HostVersion" => "1.0.0", // optional, version string of your software
"HostTime" => date("c", strtotime("now")), // optional but recommended, current time at host
);
// Return response
echo json_encode($response);
?>
Now login to your BlissRADIUS Embedded web area at http://localhost:9071
and under Config > Host API set http://localhost/my_billing/api.php
as API URL.
Make sure that blissembed
is set as username and password, then press Test API button. If everything is correct you will get confirmation that host is responding correctly.
Change URL in browser address bar to http://localhost:9071/service?id=1
to open service details page. You should be able to see full service details
fetched from PHP script you have just created.
This is basic principle how things work. Next step, once you complete this tutorial, is to modify script to query real data from your database and return real service information.
Calling back when changes occur
BlissRADIUS Embedded caches all service data fetched from host and stores it locally. This is required for performance reasons. Without it host would have to respond to hundreds of requests per second, which is out of reach for vast majority of billing software solutions.
Because of caching BlissRADIUS Embedded can't know if service data is up to date. It is up to host to notify BlissRADIUS Embedded when changes occur and instruct it to empty cache for services changed.
Your billing software must make empty_cache API call to BlissRADIUS Embedded every time this happens directly or indirectly.
Empty cache by using these parameters after these events:
service_id
- single service is changed in any way (deleted, disabled, enabled, suspended, topups or options are edited etc.) so empty cache for itproduct_id
- if product name or options are changed or product is deleted, all of its services are affected, so empty cache of all of themclient_id
- if clients name, email or phone number is changed or client is deleted, all of its services are affected, so empty cache of all of themusername
- if you change username for a service, you must empty cache for both old and new username
Empty whole cache (call without parameters) is used as last resort if some change in your billing software affect services in a way not described above. This can be expensive operation as reloading large number of services may temporally overload host software.
If you suspect cache is not up to date for a service it will be once you open service details page in BlissRADIUS Embedded as this always reloads cache.
Example code below is implementation of function to call BlissRADIUS Embedded API using PHP and cURL:
<?php
// You might want to have API URL configurable separately, and not passed as parameter with every function call.
define("BLISSEMBED_API_URL", "http://localhost:9071/api");
// Calls BlissRADIUS Embedded API at URL with action and optional parameters provided as associative array.
// Returns array with two elements (bool, string) with boolean success and response text/error message.
function blissembed_api_call($action, $params=array()){
$params["action"] = $action; // add to list of parameters
$c = curl_init();
curl_setopt($c, CURLOPT_URL, BLISSEMBED_API_URL);
curl_setopt($c, CURLOPT_POST, 1);
curl_setopt($c, CURLOPT_HEADER, 0);
curl_setopt($c, CURLOPT_POSTFIELDS, http_build_query($params));
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($c, CURLOPT_CONNECTTIMEOUT, 3);
$data = curl_exec($c);
$error = curl_error($c); // will be empty string if no error
curl_close($c);
if ($data === false) {
return array(false, "server at ".BLISSEMBED_API_URL." is unreachable: PHP-cURL error: $error");
}
$data = explode("\n", $data, 2);
if (count($data) == 2)
return array($data[0] == "SUCCESS", $data[1]);
else
return array(false, "response from ".BLISSEMBED_API_URL." is invalid");
}
?>
Using function implemented you can now call BlissRADIUS Embedded through your PHP code and instruct it to empty cache for service with ID 7 because it was changed:
<?php
// Making changes to service ID 7
// .....
// Empty cache when changes done
blissembed_api_call("empty_cache", array("service_id" => 7));
?>
UI integration
Pieces of BlissRADIUS Embedded web interfaces can be injected in HTML code of your billing software. Make following API calls to BlissRADIUS Embedded to fetch them:
- html_status - to inject header with status/online users and login link to web interface.
- html_service_admin - to inject full service details and reports, including graphs, into your admin page
- html_service_client - to inject service details and reports into client side service page
- html_options_picker - to inject JavaScript picker in your product and service page for easy editing of Service options
Example code below shows how you can fetch HTML code to inject into your web page using function implemented earlier:
<?php
// Prepare to build service report page in admin area for service ID 7
// Fetch data
$response = blissembed_api_call("html_service_admin", array("id" => 7));
if ($response[0] === true){
$html_code = $response[1];
// Inject $html_code into your web page
// .....
} else {
$error_message = $response[1];
// Show $error_message in page with notification that server is unavailable or that there was a problem
// ....
}
?>
Database structure
It is up to you to organize database structure of your billing software as you desire. Below is description of concepts used by BlissRADIUS Embedded, understanding them may help you with customization:
-
There should be four distinct kind of entities (objects) that should be kept track of by your billing software: clients, products, services and topups. These objects are not stored nor visible to BlissRADIUS Embedded as it has no access to your database. Only thing BlissRADIUS Embedded knows about them is what you provide as response to
get_service
API call. It is up to you to make meaningful relations and compose service details out of them. -
Clients, products and services entities must have unique ID of integer type (used as primary key) as this is type used by BlissRADIUS Embedded storage system for statistics reports and logs.
-
Clients are owners of services. Client can own any number of services. Client should have name, phone number and email address it receives notifications at.
-
Products are templates for services. There can be any number of services of same product. Product must have name and Service options stored as string (text).
-
Services are instances of products. Services have many properties: creation date, ID of client that owns them, ID of product it inherits from, username and plain password as text fields used for authentication and Service options as text property that override product options. Services also have status of your choice (active, disabled, suspended etc.) that translate to simple boolean
true/false
as far BlissRADIUS Embedded is concerned if service is enabled or not (can connect or not). -
Topups are simple extensions to existing services options. Service can have any number of topups. Each topup has creation date, status (that translates to simple
true/false
if enabled or not), canonical name of option and amount as floating point number.
BlissRADIUS Embedded knows nothing about concepts like payments, transactions, currencies, recurring billing etc. It is up to your software to keep track of those things, and if needed, change service properties. Eg. if monthly billed service fails to renew then change status from active to suspended and inform BlissRADIUS Embedded to reload service.
Tips
-
If you are not using integer primary keys in your database tables (which is not recommended) then you must have separate unique column of that type. These integer IDs are connection between all statistics and logs stored in BlissRADIUS Embedded and your services/products/clients. It is perfectly doable to migrate data from WHMCS to Blesta to your billing software and back if you manage to preserve IDs during migration.
-
Service passwords must be stored as plain text or be decryptable by your software if stored encrypted. RADIUS requires password in plain text format to be able to use it with all current and future authentication methods.
-
Host API script is best secured by IP locking (permit only known IP of your BlissRADIUS Embedded server). Username/password authentication is nice to have but rarely needed in production.
-
JSON output field keys are case sensitive, you must use them exactly as shown in PHP script example.
-
With
send_email
API call always check parameters. BlissRADIUS Embedded doesn't guarantees email address is valid, or thatservice_id
orclient_id
are pointing to existing entities. When sending test email these are set to zero and only address is used. -
get_service
call should always be flexible when looking up services. If more than one service share same username, always return newest/active service. Return details even when matching service is disabled or long expired. It is more helpful to have service disabled: GB limit reached than service not found when troubleshooting failed login attempts by client. -
Store service usernames in database in lower case and strip white space from ends. RADIUS authentication is case insensitive so this will increase performance and prevent common problems with leading/trailing invisible characters.
-
Passwords should be also be stripped of white spaces from ends. This is common cause for failed logins.
-
All dates returned in
get_service
JSON output are formatted as ISO 8601 strings. PHP date('c', ...) function may help with this. -
get_service
JSON output fieldOptions
holds string aggregate of product and service options separated by newline. Order is important. Duplicated options will be overridden during parsing, it is expected behavior. This way service options take precedence over product options.
Copyright © 2014 - 2025 LightBulb Software™ All Rights Reserved.

- 2025-03-16
- Referral program is active, existing users can win bonus license time if they bring new customers in.
- 2025-03-02
- BlissRADIUS Embedded™ 1.16 is out with new features.
- 2024-09-27
- BlissRADIUS Embedded™ 1.15 is out with postpaid license support.
- 2024-09-19
- We are introducing changes to payment methods. See Home page for more details.
- 2023-07-06
- BlissRADIUS Embedded™ 1.14 is out with new features.
- 2022-11-18
- BlissRADIUS Embedded™ 1.13 is released with new fixes and features.
- 2021-12-31
- BlissRADIUS Embedded™ 1.12 is out with new features.
- 2021-06-22
- Volume discount for monthly BlissRADIUS™ licenses is available now.