Skip to main content

Billing systems

A billing system creates an account when an order is paid, suspends it when an invoice is overdue, and deletes it when the service is cancelled. It does that over the Server API with a server API key (API Keys), and it hands the new account holder the setup link the server answers with. Nothing is installed on the server for it. The billing system's module, such as the WHMCS module, is documented with the module: where to enter the server's hostname and the key, and how its products map to the account limits.

What the billing system needs​

An admin user of its own, and a key that acts as it:

elpanctl server:admin-user:create <admin>
elpanctl server:api-key:create <admin> whmcs --scope=all:readwrite

The installer's closing message names these two commands as the way to link to WHMCS. --scope=all:readwrite is needed because the default scope is read-only and creating an account is a write (API Keys). Give the system:

  • the server's admin host, https://admin.<server hostname>/, which is where /api/v1 is (the bare hostname serves it too, see Server API);
  • the token, espat_…, which the command prints once.
An admin user per system

A key acts as its admin user, and what the key does is recorded against the key (a deletion's requestedBy is api:<key id>). An admin user that exists only for the billing system keeps its actions apart from yours, and deleting that user revokes its keys in one step. server:admin-user:create makes it passwordless; the API checks the key, not whether anyone finished that user's setup link, so its keys work as they are.

What it calls​

Step in the billing systemServer API operation
Order paid: create the accountPOST /api/v1/accounts with the username and the limits of the product (storageLimit, memoryLimit, cpuQuota, the mailing list and webhook limits, …). The response carries the account's single-use setup link and PIN.
Add the ordered domainPOST /api/v1/accounts/{username}/domains with the domain. It provisions the domain's services: identity, mail, website and the www alias.
Change of productPATCH /api/v1/accounts/{username} with the limits that change.
Invoice overduePOST /api/v1/accounts/{username}/suspension. Sign-in, mail, FTP, websites and databases stop; nothing is deleted.
Invoice paidDELETE /api/v1/accounts/{username}/suspension.
Service cancelledDELETE /api/v1/accounts/{username}: once to terminate, which starts the grace period, and again to purge once it has elapsed, or with immediate=true.
Cancellation withdrawnDELETE /api/v1/accounts/{username}/termination. The account comes back suspended.
The holder lost their passwordPOST /api/v1/accounts/{username}/setup-links for a new setup link.
Sign in as the holderPOST /api/v1/accounts/{username}/impersonations for a one-shot URL.

Suspend, terminate and delete an account explains the states, the grace period and what a purge removes; Limits explains each limit and its default.

A new account has no password. The POST /api/v1/accounts response carries a setupLink with a url the holder opens, a claimUrl with a pin for a hand-off over the phone, and an expiresAt. It is shown in this response only. The billing system's welcome message is where it belongs; if it is lost, POST /api/v1/accounts/{username}/setup-links issues a new one and invalidates the old.

Usernames are never reused

A username that belonged to a deleted account is refused with 409. A billing system that derives the username from the order must not expect to recreate an account under the same name after a purge.

What it gets back​

The server's Webhooks tell the billing system what happened without polling. The account.* family is the one to subscribe: account.created, account.suspended, account.unsuspended, account.terminated, account.restored and account.removed, and account.purge.succeeded or account.purge.failed when a deletion ends. quota.threshold_crossed says that an account reached 80 %, 95 % or 100 % of its storage.

elpanctl webhook:endpoint:create --server "WHMCS" https://billing.example.net/elpan-hook --event="account.*" --event="quota.*"

Inside the account​

The server API stops at the account's border: it creates the account and its first domain, but it does not create a mailbox or a database inside it. A billing system that provisions more than that creates a key for the account with POST /api/v1/accounts/{username}/api-keys and uses the account API with it, as the account holder would.