The Access4 (Sasboss) integration pulls enterprises, service accounts, DID numbers and billing charges into PracBill every night so you can bill Access4 services without manual entry. Commands on this page are run by PracBill support on your behalf.
| Data | Source | Destination |
|---|---|---|
| Enterprise | Sasboss enterprise | PracBill customer |
| DID numbers (single or blocks) | Sasboss DID numbers | Engineering (DID) records |
| Service accounts (endpoints, hunt groups, IVRs, call centres, fax lines and so on) | Sasboss service accounts | Engineering (licence) records |
| Wholesale cost | Sasboss billing charges | Engineering cost |
| Retail price | Pricing rules below | Engineering monthlyfee |
| Setup fees | Sasboss billing charges | Engineering items (unbilled line items) |
The sync runs nightly at 00:30 (access4:sync-all). It is idempotent: re-running it creates no duplicates.
Each enterprise produces two kinds of engineering record, matching how Access4 bills (DID charges and user licences are separate lines). A DID with an endpoint attached therefore produces two records.
| Record | One per | Charge carried |
|---|---|---|
| DID record | DID number, or DID block for 10 and 100 number ranges. Block size comes from Sasboss didNumberGroupSize (1, 10 or 100); PracBill never guesses ranges. |
DID rental from the billing API, e.g. $0.35/month per number. |
| Service account record | Provisioned service account, with or without a DID. | User licence charge, e.g. $35/month for an Executive User. Several charges on one serviceId (e.g. Executive User plus Collaboration add-on) are summed. |
Retail price (monthlyfee) is resolved in this order:
| Priority | Rule | Use it for |
|---|---|---|
| 1 | Price book override: the customer has a price_book_id and the price book has a price for the service type |
Customer-specific pricing. Create a price book, set per-service-type prices, assign it to the customer. |
| 2 | Service type list price: list_price on the service type |
Charging more than wholesale for everyone, e.g. DID Number at $1.00 when wholesale is $0.35. One-off setup. |
| 3 | Wholesale pass-through (default) | Retail = wholesale cost from Access4. You never undercharge; at worst you break even. If Access4 changes the wholesale price, retail follows on the next sync. |
The sync never sets list_price when it creates a service type. New products start on pass-through until you set a list price.
Each Access4 billing product (productId) maps to a service type through vendor_product_id. New products create service types automatically.
| Product | Description | Typical wholesale |
|---|---|---|
| 6408 | Executive User | $15 to $35 |
| 6414 | Collaboration User | $25 to $40 |
| 6405 | Office User | $10 to $25 |
| 6492 | DID Number (1) | $0.35 to $1.00 |
| 6495 | DID Number Block (10) | $3.51 to $10 |
| 6498 | DID Number Block (100) | $35 to $39 |
| 6486 | Business Trunk | $8.97 to $50 |
Default (rollup): each Sasboss enterprise is one PracBill customer. All groups, sites and services roll up to it. One bill, one record.
Split by group (opt-in): for enterprises with several sites configured as Sasboss groups that want a bill per site. When enabled on the parent customer:
Enterprise Name - Group Name.By customer name (case-insensitive substring match against the Sasboss enterprise list):
php artisan access4:enable-split-by-group {deptId} "Customer Name 1" "Customer Name 2"
php artisan access4:enable-split-by-group 165 "Melbourne Racing Club" "Estia" "Iron Mountain" "Calvary Health"
By customer ID:
php artisan access4:enable-split-by-group 165 --cid=7088777
The command authenticates with Sasboss, finds the matching enterprise, finds or creates the enterprise mapping, and inserts a config mapping with external_source = 'access4_config' and external_id = 'split_by_group'.
php artisan access4:enable-split-by-group 165 "Melbourne Racing Club" --disable
On the next sync everything rolls back under the parent: group customer services are terminated and re-created on the parent.
After enabling or disabling split by group, or changing service type pricing, run the sync:
# Single enterprise (fast)
php artisan access4:sync-services 165 --enterprise-id=5656
# Full sync
php artisan access4:sync-services 165
Rolls back group customers created by mistake:
php artisan access4:cleanup-group-customers 165 --dry-run # preview
php artisan access4:cleanup-group-customers 165 # apply
It skips customers with invoices or quotes, re-homes engineering records to the parent enterprise customer, and soft-deletes the group customer and its mapping.
Compares what Access4 bills you with what PracBill has captured:
php artisan access4:billing-gap-report 165 --top=20
php artisan access4:billing-gap-report 165 --csv=gap_report.csv
list_price on service types where retail should exceed wholesale (e.g. DID Numbers at $1.00).access4:sync-services {deptId} to import all services.access4:enable-split-by-group.| Symptom | Cause | Fix |
|---|---|---|
| Retail = wholesale for every service | No list_price on the service type |
Correct default. Set list_price where retail should be higher. |
| Customer has too many engineering records | Groups being split per site | Check whether split_by_group is enabled; disable if not wanted. |
| Services missing after sync | New product type not yet matched | Check whether a new service type was auto-created; set its pricing. |
| Duplicate customers | Access4 name differs from the imported name | Use the cleanup command or merge manually. |
| Auth fails (HTTP 401) | Credentials expired or the application key changed | Re-save the credentials in the Integrations UI. |
| Item | Value |
|---|---|
| Enterprise mapping | external_source = 'access4', external_id = 'enterprise:{id}' |
| Group mapping | external_source = 'access4', external_id = 'group:{id}' |
| Split-by-group flag | external_source = 'access4_config', external_id = 'split_by_group' |
| Nightly schedule | 00:30 daily via access4:sync-all |
| Pricing resolution | Price book, then service type list_price, then wholesale pass-through |
Related: Integrations, Create service types.