Source version and installed-release boundary
This manual covers the reviewed newer product source workflow. It requires its matching released core, additive database structure and signed modules where applicable. The separately approved licensed 1.3.8 archive can have an earlier workflow. Do not assume these screens or commands exist merely from a numeric version label, and do not copy newer source files over a signed installation. Documentation publication does not upgrade the product or enable any external account.
Migration accepts exported data, never an executable database dump, PHP script or source API credential. A preview validates the source rows before any import. The new workspace is separate from the older WHMCS literal SQL cutover tools; that original cutover runner expects a specific empty/sample installation and must not be reused against an established business.
Supported native exports
The source adapter reads the following documented fields. It does not claim that a customer-list response is a complete business export. For collections outside a source's native coverage, choose Mapped CSV / JSON and map the exported columns explicitly.
| Source | Native collections | Export guidance |
|---|---|---|
| WHMCS | Customers, products, hosting services, domains | Export GetClientsDetails, GetProducts, GetClientsProducts and GetClientsDomains. Service rows omit currency, so include each customer's currency_code or an explicit customer currency map. Only quantity-one service rows have an unambiguous supported total. |
| ClientExec | Customers | Export Get Users; include Get User detail fields inside each row when address data is needed. Public package documentation describes write operations and the public invoice example lacks complete numeric financial detail, so those records require mapped files. |
| Blesta | Customers, products/packages | Export Clients/get with settings and Packages/getAll or package detail. Choose one language for multilingual package names. A standard Blesta package becomes a generic product until its provider type is reviewed. |
| HostBill | Customers, hosting services, domains | Export getClientDetails, getAccountDetails, getDomains. The accounts list alone omits the product reference needed for migration. Include a source currency-id map if a detail row lacks currency.code. |
| WISECP | Customers, products, services | Export Admin API client, product and service lists. Resolve currency ids explicitly. Multi-quantity services need a mapped final recurring amount. API numeric decimals remain exact strings when the upload decoder reads them. |
| FOSSBilling | Customers, products, services/orders | Export the Admin client/product/order API records. Customer CSV export is also supported. Orders use their supplied total; multi-quantity or discounted orders need an explicitly mapped final recurring amount. |
| BoxBilling | Customers, products, services/orders | Uses the legacy published serializers, with the same explicit quantity and discount restrictions. Credentials and module-specific config are excluded. |
| Upmind | Customers | Export Admin clients API records with firstname, lastname, email and currency_code. Map contract, financial and support exports explicitly; contracts are not inferred to be hosting accounts. |
Native mappings deliberately do not migrate passwords, source access tokens, saved payment methods, provider credentials, provisioning module configuration, seller identity or business settings. Product catalogue entries do not automatically configure a live hosting server. Reconcile provider ownership separately before enabling automation.
JSON envelope
Use a stable source_instance for the original installation so a later batch can identify the same source. It contains at most 80 ASCII letters, digits, dots, underscores or hyphens. Do not put a username, password or API URL with credentials in this field.
{
"schema": 1,
"source_instance": "old-billing.example.test",
"records": {
"customers": [
{"id": "42", "firstname": "Example", "lastname": "Client", "email": "client@example.test", "currency_code": "AUD"}
],
"products": [
{"pid": "7", "type": "hostingaccount", "name": "Shared hosting"}
],
"services": [
{"id": "51", "clientid": "42", "pid": "7", "name": "Shared hosting", "qty": "1", "domain": "site.example.test", "recurringamount": "120.00", "billingcycle": "Annually", "status": "Active", "nextduedate": "2027-06-01"}
]
},
"source_counts": {"customers": 1, "products": 1, "services": 1}
}
The example above uses the WHMCS adapter. Every source uses the same envelope with that source's native rows inside the named collections. A collection may also contain a complete documented API response wrapper. Merge every page into a single row array first: responses with another-page markers or a total greater than the included row count are rejected. Source counts are optional but, when supplied, must match exactly.
HostBill and WISECP can resolve source currency identifiers with an explicit map:
{"currencies": {"0": "USD", "1": "AUD"}}
Every native customer adapter can use "customer_currencies": {"42": "AUD"} when its response omits a currency code. This map is required for ClientExec user responses. WHMCS service-only batches can use "customer_currencies": {"42": "AUD"}. These are explicit source mappings; no default currency or exchange rate is guessed. Historical invoice currency must be supplied independently and must never be copied from a customer's current preference.
Canonical mapped collections
Choose mapped for canonical JSON or use a CSV column map. Each record is an object with allowlisted fields only. Fields in bold are required. References always identify source records, not target database ids.
| Collection | Fields |
|---|---|
customers |
id, email, name, currency, company, phone, country, address, city, region, postal_code, status |
products |
id, name, type, description |
services |
id, customer_id, product_id, name, currency, cycle, amount, status, domain, next_due_date, username |
domains |
id, customer_id, domain, status, service_id, expires_on, nameservers |
invoices |
id, customer_id, number, currency, issue_date, due_date, subtotal, discount, tax, total, paid, status |
invoice_items |
id, invoice_id, description, amount, service_id |
payments |
id, invoice_id, currency, amount, direction, received_on, reference |
tickets |
id, customer_id, subject, status, body, created_at |
- Ids and references are stable source strings, at most 100 characters. Duplicate ids within one collection are rejected.
- Money uses exact decimal strings, for example
"120.00". Symbols, grouping separators, scientific notation, floating-point values passed to the PHP normalizer, and amounts with more than two decimal places are rejected. Uploaded JSON decimal tokens are preserved before normalization. All native amounts are non-negative. Negative credit notes or credit lines require separate financial reconciliation; the importer rejects them rather than inverting or discarding them. - Currencies use uppercase three-letter ISO codes. Countries use uppercase two-letter codes. Missing currencies are not inferred from symbols or installation settings.
- Dates use
YYYY-MM-DD. A time with an optional ISO offset is also accepted; ticketcreated_atretains its time. Localized dates and impossible dates are rejected. A zero source date is treated as unknown only for optional dates. - Service cycles are
monthly,quarterly,semiannually,annually,biennially,trienniallyorone_time. Do not shorten daily, hourly, custom-length or multi-quantity source obligations to fit a different cycle. - Product types are
shared,hosting,reseller,vps,server,domainorother(the explicitaddonalias becomesother). Unknown native plugin products becomeotherfor review. - Payment
directionisreceivedorrefund; the explicitpaymentalias normalizes toreceived. Refunds preserve their direction and positive amount; a negative credit note must not be reclassified as a receipt. nameserversis a list of at most 13 DNS host names. URLs, paths and IP addresses are not domain names. Use ASCII/punycode for international domains.
Historical invoice totals, discounts, taxes, paid amounts and payment allocations must be exported explicitly. The adapter does not turn an invoice marked paid into an invented payment transaction or replace missing tax with zero. Source financial records that cannot supply these values require reconciliation before import.
CSV mapping
CSV uses UTF-8, comma separators, a unique header row and LF or CRLF line endings. Quoted commas and newlines are supported. Limits are 10 MB, 10,000 records, 100 columns and 4,096 bytes per field. Header and row widths must match; malformed quoting is rejected.
For an export headed Client Number,Email Address,Display Name,Currency Code, the column map is:
{"id":"Client Number","email":"Email Address","name":"Display Name","currency":"Currency Code"}
The keys are canonical fields and the values are literal column headings. No expressions, source queries or callbacks are accepted. An explicit map works for any selected source brand and discards unmapped columns. Without a map, headings must match the selected native adapter's fields or, for mapped, the canonical names. CSV nameservers can contain comma-, semicolon- or whitespace-separated hosts.
Authoritative mapping references
- WHMCS client details, products, services, domains.
- ClientExec Get Users, Get User, invoice response limitations.
- Blesta API, Clients model, Packages model.
- HostBill client details, account details, domains.
- WISECP clients, products, services.
- FOSSBilling API and first-party Client, Product, Order serializers.
- BoxBilling first-party serializers.
- Upmind client API service and client field contract.

