Hosting plans & billing periods

Updated 21 Oct 2026 Published

Hosting plans & billing periods — quick guide for hosting providers

A hosting plan says what an account may use (websites, disk, databases…). A plan period says until when the account is paid for. VinzaPanel warns before the end date, keeps the account running for a few grace days, then suspends it — and brings it back as soon as you renew. Nothing is ever deleted.

Requires VinzaPanel 1.3.71 or newer.

Concepts

Term Meaning
Start date First day of the current period.
End date Last paid day. On this day the account still works. Empty = no expiry.
Billing cycle Monthly, quarterly, every 6 months, yearly, custom (N days) or no expiry. Renewing adds whole cycles.
Warn days before How many days before the end date the admins and the customer get a notice (panel bell + email).
Grace days Days after the end date during which the account keeps working.
At expiry Warn, then suspend after the grace days (default) or Warn only.
Auto-renew The panel extends the end date by one cycle by itself when it passes — for accounts you bill outside a billing system. Leave it off when WHMCS, ClientExec or Blesta renews through the API.

The status badge shows where an account is:

Status When
Active More than warn days before the end date, or no end date.
Expiring Within warn days of the end date.
Grace Past the end date, still within the grace days.
Expired Past the end date and the grace days. With suspend the account is suspended now.

A suspension caused by the expiry is lifted automatically when you renew. An account you suspended yourself for another reason (abuse, for example) stays suspended.

Set it up in 5 steps

  1. Create your plans — Administration → Hosting Plans (/plans/). See Hosting Plans.
  2. Open the account — Server → Users, click the account, then Edit.
  3. Set a period — in the Plan period card pick the start date and billing cycle. Leave End date empty to end after one cycle (monthly from 1 Jan → 31 Jan), or type an end date.
  4. Choose grace and warning — e.g. warn 7 days before, 7 grace days, Warn, then suspend. Click Save period and confirm.
  5. Check the list — the Users list shows each account's end date with an Active / Expiring / Grace / Expired tag. The background job plan_expiry (Scheduler → Background Worker Jobs) checks every account hourly; each notice is sent once per period.

Renewing

  • Renew button (edit page) — adds 1 or more cycles to the end date. Monthly periods keep their day of month (a period that started on the 31st ends on the 30th/31st, never drifts to the 28th).
  • Count from today — for a period that lapsed long ago: the new cycles start today instead of at the old end date.
  • Change dates & settings — type any start and end date. Remove end date makes the account never expire.

Each change is kept in the card's History (who, when, old → new end date).

API (billing systems)

All calls use a token with the Provisioning scope (Profile → API tokens) and the same rules as the Provisioning API: Authorization: Bearer …, JSON bodies, optional Idempotency-Key header on POSTs.

PANEL=https://panel.example.com:2711/api/v1/provisioning
TOKEN=vzp_xxxxxxxxxxxxxxxx

Assign a plan with a yearly period

curl -s -X POST "$PANEL/accounts/alice/period/" \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-1001" \
  -d '{"plan": "Business", "start_date": "2026-11-01", "cycle": "yearly",
       "grace_days": 7, "notify_days": 14, "on_expiry": "suspend"}'
{"success": true, "username": "alice", "status": "active",
 "plan": {"id": "3", "name": "Business"},
 "period": {"start_date": "2026-11-01", "end_date": "2027-10-31", "cycle": "yearly",
            "cycle_days": 30, "auto_renew": false, "grace_days": 7, "notify_days": 14,
            "on_expiry": "suspend", "status": "active", "days_left": 360,
            "grace_ends": "2027-11-07", "suspended_for_expiry": false,
            "history": [{"action": "assign", "actor": "billing (api:whmcs)", "old_end": null,
                         "new_end": "2027-10-31", "at": "2026-11-01T08:00:00+00:00", "...": "..."}]}}

Every field is optional; fields you leave out keep their value. "cycle": "none" removes the end date, "plan": null removes the plan.

Renew after payment — one more cycle, or an exact end date:

curl -s -X POST "$PANEL/accounts/alice/period/renew/" \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -H "Idempotency-Key: invoice-5521" \
  -d '{"cycles": 1}'

curl -s -X POST "$PANEL/accounts/alice/period/renew/" \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"end_date": "2028-12-31"}'

Add "from_today": true to restart a long-lapsed period today. The answer has the same shape as above; a suspension caused by the expiry is lifted in the same call.

Read an account's period

curl -s "$PANEL/accounts/alice/period/" -H "Authorization: Bearer $TOKEN"

GET /accounts/alice/ also includes it as plan_period (null = no period).

List accounts that expire soon (default 14 days, expired ones included):

curl -s "$PANEL/expiring/?days=30&include_expired=false" -H "Authorization: Bearer $TOKEN"
{"success": true, "days": 30, "total": 1,
 "accounts": [{"username": "alice", "email": "[email protected]", "plan": "Business",
               "suspended": false,
               "period": {"end_date": "2026-11-20", "status": "expiring", "days_left": 12, "...": "..."}}]}

Errors answer 400 with {"success": false, "error": "…"} (bad date, unknown cycle or plan, renewing an account without a period), 403 for admin accounts or a token without user-management rights, 404 for an unknown username.

On this page