Basic External Provisioning and Web Service Contacts¶
This guide describes a minimal deployment of Acrobits external provisioning and Web Service Contacts using the example PHP scripts from the integration-snippets repository.
The example service does two things:
- Validates the user against a CSV file and returns Account XML for external provisioning.
- Returns a JSON contacts list from the same CSV data for Web Service Contacts.
Use this as a starting point for simple deployments or proof-of-concept integrations. For production, review the security and scaling notes before exposing the service to end users.
Source Files¶
Download or copy these files from the snippet repository:
helpers.phpacrobits_prov.phpacrobits_contacts.phpexample-data/extProv/SAMPLE.xmlexample-data/users/SAMPLE.csv
Server Requirements¶
The server needs:
- PHP 7.4 or newer.
- A web server with PHP support, such as Apache or Nginx with PHP-FPM.
- HTTPS enabled.
- Read access from the PHP process to
/srv/data/provisioning/.
HTTPS is required because the provisioning endpoint receives user credentials in the request.
Deploy the PHP Files¶
Place the PHP files together in a public web directory:
The public URLs will then look like this:
https://customer-domain.example/provisioning/acrobits_prov.php
https://customer-domain.example/provisioning/acrobits_contacts.php
Prepare the Data Directory¶
Store customer data outside the public web root. The example scripts use this layout:
The filename must match the cloud_id. Use uppercase filenames, for example SAMPLE.csv and SAMPLE.xml for cloud_id=SAMPLE.
The scripts also normalize editable Cloud Softphone versions by stripping a trailing * from the Cloud ID, so SAMPLE* and SAMPLE use the same data files.
Create the User CSV¶
Place the user CSV file at:
The sample CSV uses this structure:
cloud_username,cloud_password,username,password,display_name,first_name,last_name,avatar,phone_number1
user001,SAMPLE_PASSWORD,1001,ACCOUNT_PASSWORD_1001,Example User One,Example,User One,https://example.com/avatar-user001.png,1001
user002,bcrypt:<bcrypt_hash_for_user002>,1002,ACCOUNT_PASSWORD_1002,Example User Two,Example,User Two,https://example.com/avatar-user002.png,1002
The provisioning endpoint looks up users by cloud_username.
The cloud_password value can be stored as:
- Plain text, useful only for quick local testing.
- A bcrypt hash in the format
bcrypt:<hash>, recommended for real deployments.
The username and password columns are the SIP account credentials returned in the Account XML. The cloud_username and cloud_password columns are the credentials entered by the user during app activation.
Create the Account XML Template¶
Place the external provisioning XML template at:
The XML template may contain placeholders matching CSV column names. During provisioning, placeholders such as {username}, {password}, and {display_name} are replaced with values from the matching CSV row.
Example:
<account>
<title>{display_name}</title>
<acrobitsDisplayName>{display_name}</acrobitsDisplayName>
<cloud_id>{cloud_id}</cloud_id>
<cloud_username>{cloud_username}</cloud_username>
<cloud_password>{cloud_password}</cloud_password>
<username>{username}</username>
<password>{password}</password>
</account>
{cloud_password} is replaced with the password submitted by the app after validation succeeds, not with the stored CSV value. This prevents a stored bcrypt hash from being returned to the app.
Add Web Service Contacts Configuration¶
If you want the same deployment to enable Web Service Contacts, add the wsContacts* settings to the Account XML returned by external provisioning, or configure equivalent values in the Cloud Softphone portal.
Example Account XML fragment:
<wsContactsUrl>https://customer-domain.example/provisioning/acrobits_contacts.php?cloud_id=%account[cloud_id]%&cloud_username=%account[cloud_username]%</wsContactsUrl>
<wsContactsMethod>GET</wsContactsMethod>
<wsContactsRefresh>180</wsContactsRefresh>
The contacts endpoint returns JSON in the format expected by Web Service Contacts:
{
"contacts": [
{
"fname": "Example",
"lname": "User Two",
"displayName": "Example User Two",
"contactId": "1002",
"cloudUsername": "user002",
"networkId": "SAMPLE",
"avatar": "https://example.com/avatar-user002.png",
"largeAvatar": "https://example.com/avatar-user002.png",
"contactEntries": [
{
"entryId": "tel:sip",
"label": "SIP extension",
"type": "tel",
"uri": "1002"
}
]
}
]
}
The sample contacts script skips the requesting user's own cloud_username, uses username as contactId when available, and maps phone_number1 through phone_number5 into additional phone entries.
Configure Initial External Provisioning¶
In the Cloud Softphone portal, configure initial external provisioning to call the PHP provisioning endpoint.
Use a URL like this:
https://customer-domain.example/provisioning/acrobits_prov.php?cloud_id=%fullcode%&cloud_username=%username%&cloud_password=%password%
Use GET for the basic example.
The placeholders are expanded by the app during initial provisioning:
%fullcode%is the Cloud ID.%username%is the username entered by the user.%password%is the password entered by the user.
The PHP script validates the submitted credentials against the CSV row. If validation succeeds, it returns the XML template with placeholders replaced by values from that row.
Test the Deployment¶
Test external provisioning:
curl "https://customer-domain.example/provisioning/acrobits_prov.php?cloud_id=SAMPLE&cloud_username=user001&cloud_password=SAMPLE_PASSWORD"
Expected result: an XML response with one <account> root node.
Test Web Service Contacts:
curl "https://customer-domain.example/provisioning/acrobits_contacts.php?cloud_id=SAMPLE&cloud_username=user001"
Expected result: a JSON response containing a contacts array.
If the provisioning password is invalid, the sample provisioning script returns HTTP 410 with a JSON error body.
Production Notes¶
Keep /srv/data/provisioning/ outside the public web directory. The CSV file may contain passwords and must not be directly downloadable.
Use bcrypt hashes for cloud_password values instead of plain text passwords.
Restrict file permissions so only the web server process can read the provisioning data.
The sample contacts script is intentionally simple and does not implement Last-Modified or 304 Not Modified handling. For large contact lists, add caching support so apps do not download the full contacts payload every refresh interval.
Validate and escape any additional fields you add to the XML template. The sample provisioning script escapes placeholder values with htmlspecialchars() before returning XML.