Knowledge base
Sell Zinn® hosting from WHMCS
Install the free Zinn Digital provisioning module in WHMCS: the API key and the seven permissions it needs, where the module directory has to go and why its name matters, the product fields, and what each WHMCS button actually does.
The Zinn Digital® module turns WHMCS's own buttons into real actions on our platform. An order provisions your client's hosting. WHMCS's overdue-invoice automation suspends it. Marking the invoice paid releases it. Cancelling schedules the deletion. And your client gets a Log in to hosting panel button in their client area that signs them straight in.
It is free, GPL-2.0-or-later licensed, and has no privileged path into our platform: every call it makes is a documented endpoint that you could make yourself with your own API key.
Before you start
You need two things, and the second one catches people out.
- A Zinn® reseller account with an active programme. Sign up at
- A reseller plan with site allowance. Sites your clients order count against your
zinndigital.com and turn on reselling.
plan, so you need one with room in it.
⚠️ Test Connection cannot tell you whether an order will succeed. It reads your programme and provisions nothing, so it reports a healthy
activeaccount that cannot yet sell anything. If your first order fails with "This organization has no hosting plan, so it cannot host a site yet", that is what has happened — buy or extend your reseller plan and place the order again. Nothing is wrong with the module.
1. Create the API key
In your Zinn® dashboard, open API keys and create one with exactly these eleven permissions:
| Permission | Why it is needed | | -------------------- | ----------------------------------------------------------- | | org.create | Open your client's Zinn® account on their first order. | | org.read | Read your client accounts. | | sites.create | Provision the site. | | sites.view | Read a service and its usage. | | sites.delete | Terminate. | | reseller.view | List what you have sold, and read disk and bandwidth. | | reseller.provision | Suspend, release, sign a client in, set their plan and change their package. | | billing.view | Read what an upgrade would cost before performing it. | | sites.manage | Purge cache and take a backup from the buttons. | | sites.panel_access | Change the WordPress administrator's password. | | hosting.php.manage | Switch PHP version on an upgrade or downgrade. |
⛔ Do not grant
reseller.manage. A key pasted into a billing panel should be able to hold a client for non-payment and sign them in. It should not be able to read and rewrite your own payment-gateway credentials.reseller.provisionexists so you do not have to grant the bigger one. ⛔org.createis not optional. Without it the module can read your accounts and cannot open one, so Test Connection passes and the first order answers403. ⛔⛔ Grant the whole table, and note that Test Connection cannot tell you if you have not. It reads your reseller programme and provisions nothing, so it is green for a key missing any of these. What you get instead is a403on the one operation the missing permission covers, months later, from a customer.
2. Install the module
- Download the module and unzip it.
- Upload the
zinndirectory into your WHMCS installation so the module file lands at
modules/servers/zinn/zinn.php.
⛔ The directory must be called
zinn. WHMCS derives a provisioning module's function names from its directory name, so renaming it tozinn-whmcsorzinndigitalproduces a module WHMCS lists, lets you select, and then never calls — with no error anywhere. The zip already unpacks to the right name; just do not rename it.
3. Add the server
In WHMCS: Configuration → System Settings → Servers → Add New Server.
- Name: anything, e.g.
Zinn Digital® - Hostname:
api.zinndigital.com - Type:
Zinn Digital® - Password: your API key from step 1
⛔ The key goes in the Password field, which WHMCS stores encrypted. Do not put it in a product configuration option — those are plain text in the database and visible to every admin, and this credential can create and destroy your clients' hosting.
Press Test Connection. It makes a real call and reports what our platform said, rather than checking that the fields are filled in.
4. Create the product
Configuration → System Settings → Products/Services, then set Module Settings to the server you just added. The fields are:
| Field | Required | What it is | | ---------------- | -------- | -------------------------------------------------------------------------- | | Product line | yes | The Zinn® line you are selling — mainstream (managed WordPress), footprint_free, wordpress, linux, cloud, agency, app_hosting, ai_hosting, lms_hosting, managed_database, vector_hosting, zinn_compute, fleet_linux, fleet_enterprise, mail or reseller. | | Stack | yes | What gets built: wordpress (default), woocommerce, php, static, node, one_click, headless_cms, nextcloud or owncloud. | | Application | no | Only for the one_click and headless_cms stacks — which application to install. Naming one on any other stack is refused, because that stack already decides what gets installed. | | PHP version | no | e.g. 8.3. Leave empty for the line's default. A version the line does not offer is refused with the list of the ones it does. | | Plan code | yes | The Zinn® plan this product sells. GET /v1/reseller/prices lists yours. An order without it is refused — see the warning below. | | Billing interval | no | monthly (default) or annual — the interval your wholesale line for this client is raised on. What you charge your own client is set on the WHMCS product and is unaffected. |
⛔⛔ Plan code is required, and an order without one is refused on purpose. Until 2026-09-01 the field was decorative and nothing read it, so the module ordered hosting that carried no plan at all — and every consequence of that was silent. Your wholesale statement is built from your clients' live subscriptions, so there was no line for the service and you were invoiced nothing for as long as it ran; your client inherited no allowances, so no disk or file quota was applied to their site; and Change Package had nothing to change, so an upgrade you sold could not be performed. The site provisioned and served perfectly throughout.
The module now refuses the order instead, because there is no safe plan for it to guess: a guess would provision hosting on a plan you did not choose and may not have priced, and — unlike a refusal, which you read immediately — it would surface only when a statement arrived, if at all.
Set Auto Setup to whichever you prefer — the module is idempotent on the WHMCS service id, so a retried provision returns the same site rather than billing you for a second one.
What each WHMCS action does
| WHMCS action | What happens on our side | | --------------------------- | ---------------------------------------------------------------------------------------- | | Create | Creates the client's Zinn® account (or reuses the one they already have) and provisions their site. | | Suspend | Puts the site on a non-payment hold. Content is retained; nothing is deleted. | | Unsuspend | Releases your hold. | | Terminate | Schedules the site's deletion, with a grace period. The date shows in the client area. | | Usage update | Refreshes disk and bandwidth on every service, once a day. | | Log in to hosting panel | Opens a one-time, single-use sign-in link straight into your client's panel. | | Change Package | Upgrades or downgrades the service. Moves the package, and the PHP version if the new product names one. | | Change Password | Sets the WordPress administrator's password. The box does not appear on stacks that have no such account. | | Renew | Confirms the service still exists. Zinn® hosting is continuous, so there is no remote term to extend. | | Sync Usage / Purge Cache / Take Backup | Buttons on the admin service page. Your client gets Purge Cache and Take Backup in their client area. | | Service tab | Status, plan, disk, bandwidth, any scheduled deletion, and who placed a suspension. | | Import | ListAccounts reads every page, so an import cannot silently stop at the first one. |
Upgrades: who charges whom
Your client is never invoiced by Zinn®, on an order or on an upgrade. You bill them through WHMCS; we bill you, on your wholesale statement. So a Change Package moves your client's entitlements and the line on your next statement, and touches no card — WHMCS has already taken your client's money and computed its own proration.
A client's second service. On the same plan it is another site under that plan's own site allowance, and nothing further is granted. On a different plan it is refused: replacing the live plan would leave one of the two services unbilled. Either sell both on the same plan, or set the client up as a separate client record in WHMCS.
Change Password exists only for WordPress. Zinn® hosting has no single "service password" — your client reaches their panel with the sign-in button — and a php or static site has no application account to change. WHMCS hides the box entirely rather than showing one that cannot work.
Three answers you must not flatten into two
- Unsuspend can answer with a refusal. That means the site was suspended by our abuse
- Terminate schedules a deletion, it does not perform one. The date comes back as
- Disk and bandwidth can be unknown, and unknown is not zero. When we could not take a
team, not by you, and no billing panel may release it. The message says so; show it to your admin rather than retrying.
pending_deletion_at and the client area shows it. Telling a customer their data is already gone when it is not is worse than telling them nothing.
reading the module leaves the figure alone rather than writing 0 — otherwise WHMCS would show your customer a reassuring empty usage bar for a site we have no reading from.
Troubleshooting
Test Connection passes and the first order fails with a permission error. The API key is missing org.create. The module has to open the client's account before it can create their site.
An order fails saying the organization has no hosting plan. Your reseller plan has no site allowance left, or you do not hold one yet. See Before you start above.
An order fails mentioning a stack. The Stack field on the product is empty or names something we do not build. Set it to wordpress unless you are selling something else.
Cancellations are failing. Make sure you are on module version 1.0.0 or later. Earlier builds sent no deletion confirmation and every termination was refused, which left the service running and billing.
A refusal that names a field. Our validation errors name the field and the reason in brackets after the message, e.g. (php_version: 7.2 is not offered on this product line). That is the actionable half — the sentence in front of it is deliberately generic.
Verify your download
Every archive is served over TLS from our own hostname and never redirected to a third-party host. Its SHA-256 checksum is printed beside the download link on the downloads page. Compare it after downloading:
- macOS or Linux:
shasum -a 256 zinn-whmcs-1.0.0.zip - Windows:
certutil -hashfile zinn-whmcs-1.0.0.zip SHA256
Not on WHMCS?
There is a HostBill module and a single-file PHP client for anything else, both free and both on the same downloads page. Every endpoint the modules use is in the API reference.
Still stuck?
Support is included on every plan and answers in your own language.
Contact support → All articles →