Billing for operators
Learn how billing for operators work in SPCBot and how to configure them for your team.
Visual Guide
Drop real screenshots into the paths below. This grid is rendered by src/app/docs/components/image-placeholder.tsx.
Dashboard Overview
Main dashboard with stats and recent deployments
public/docs/images/dashboard-overview.pngServer List
Connected servers and their health status
public/docs/images/servers-list.pngDeployment View
Live deployment logs and progress
public/docs/images/deployment-view.pngHow to set up and run billing for your SPCBot platform: plans, putting organizations on them, the automatic timeline, confirming payments, and the Odoo and Stripe connections. For the customer's side, see Billing for customers. For developer detail, see docs/BILLING.md in the repository.
Billing does nothing until you switch it on. An organization with no plan is never billed or limited, so turning it on affects only organizations you put on a plan. An unpaid invoice never stops anything that is running; it only refuses creating new servers, projects and environments.
1. Set up billing
Open Admin → Billing → Settings.
| Setting | Meaning |
|---|---|
| Enabled | The master switch. Off: no invoices, no limits, no emails, no scheduled work. |
| Currency | Three capital letters, for the whole platform. |
| Tax rate and label | Added to every invoice (for example VAT 15). Frozen on each invoice when it is made. |
| Payment terms (days) | Due date = issue date + this. Default 14. |
| Grace days | Days past due before new work pauses. Default 14; 0 pauses on the due date itself. |
| Auto-issue | On: each renewal is issued and emailed as its period starts. Off: renewals are created as drafts for you to review and send (a draft never pauses anyone). |
| Invoice prefix | 1 to 8 capitals or digits. Numbers look like SPC-2026-0001. |
| Company name and details, bank details, mobile-money details | Printed on invoices and shown to customers. Separate lines with | . |
2. Plans
On the Plans tab, create plans with a monthly price, an optional annual price (without one, annual bills 12 × monthly), limits on servers, projects and environments (-1 means unlimited), a trial length in days, and whether the plan is public and active. Prices are entered in the platform currency. The plan's backup-retention figure is recorded but not enforced by billing. Changing a customer's plan mid-period is not prorated; the new price applies from the next period.
3. Put an organization on a plan, a trial, or exempt
On the Organizations tab, pick an organization and set its plan, billing interval (monthly or annual), billing email (defaults to the organization's Owners) and, optionally, its Odoo partner. An organization in its trial shows a Trial until <date> chip.
- On a plan: its limits apply and it is invoiced.
- With a trial: no invoices during the trial; the first paid period begins the day the trial ends.
- Exempt from billing: never invoiced and never blocked; the plan's limits still apply. Use it for internal or complimentary organizations.
- No plan: never billed or limited.
4. The automatic timeline
One hourly job does all of this (only when billing is on). Run billing now on the Overview tab runs the same job on demand.
| When | What happens |
|---|---|
| 3 days before a trial ends | One “trial ends soon” email. |
| The trial ends | The first subscription invoice is created for the first paid period. |
| Each period start | A renewal invoice is created, and issued and emailed if auto-issue is on. A missed run catches up, billing each missed period once, but a first invoice never bills backwards. |
| Due date + 1 day | First reminder email. |
| Due date + 7 days | Second reminder email. |
| Due date + grace | New servers, projects and environments are refused, and one notice is emailed. Running systems are untouched. |
| Invoice paid | The pause lifts immediately. |
Free plans (price 0) and trials produce no invoice.
5. Invoices and confirming payments
On the Invoices tab you can create a manual invoice, edit a draft, send it, void it (a paid or void invoice cannot be voided), and record a payment (bank transfer, mobile money, cash or other; it defaults to the full amount still due, and a part payment leaves the invoice open).
When a customer submits a mobile-money or bank reference it appears as pending. Check it against your EVC Plus, Zaad, WAAFI or bank statement, then confirm it (which can mark the invoice paid) or reject it with a reason the customer will see. SPCBot never calls the mobile-money providers; this check is yours.
6. Odoo accounting sync (optional)
- In your Odoo, use or create a user with Accounting billing rights and generate an API key (Account Security → New API Key).
- In Billing → Settings, turn on “Send invoices to Odoo” and enter the URL, database, username, API key and the product name. Press Test connection; it only logs in and reads the company.
Each issued invoice becomes a posted customer invoice in Odoo for a customer partner (created if missing) on a service product, using your Odoo sale tax if one matches the rate exactly, otherwise a separate tax line. Payments flow both ways. Failures are shown on the invoice and never stop billing; they are retried every 30 minutes, and Check Odoo now or a per-invoice Sync to Odoo does it on demand. Odoo is matched by invoice number, customer and total.
If a staging platform ever uses the same Odoo as production, give staging a different invoice prefix (for example STG) so the two never issue the same invoice number.
7. Stripe card payments (optional)
- In the Stripe dashboard, copy your secret key (Developers → API keys) into Billing → Settings.
- Under Developers → Webhooks, add an endpoint at
<API>/api/v1/billing/stripe/webhooklistening for the eventcheckout.session.completed. - Copy the endpoint's signing secret into the webhook-secret setting, then turn card payments on.
Customers then see Pay by card on open invoices. A payment in a different currency, or for an invoice that is no longer open, is not recorded automatically and is logged for you to handle; refunds are not automatic. Amounts under 50 cents cannot go through Stripe Checkout.
Blocking a customer at once
To pause a customer immediately, without waiting for a trial or grace period, open Billing → Organizations and press Block now on their row. Enter a reason (the customer sees it on a red banner, on their billing page and in an email). If they are in a trial you can also tick End the trial now and send the first invoice today. New servers, projects and environments are refused at once; everything already running keeps running. The block stays until you press Unblock (on the row, or in Overview → Blocked by staff); a payment does not lift it on its own.
Demo payments (testing only)
For demonstrations and staging, turn on Demo payments (testing only) under Billing → Settings → Testing. Customers then see a Pay (demo) option: they choose a card or EVC Plus, see the payment being authorised, and the invoice is paid exactly as a real payment would be, so the lock lifts and the payment reaches Odoo. No money moves, and every demo payment is labelled Demo. Never turn this on in production.
8. The Billing manager role
On Admin → Users, set a user's platform role to Billing manager. They can use Admin → Billing (overview, invoices, plans, organizations and the billing settings) and nothing else in the admin area. They do not need to belong to any organization.
Self-service signup
Off by default. In Admin → Billing → Settings, turn on Self-service signup (billing itself must be on). Anyone with a verified account can then choose a public plan on the Pricing page, name an organization and pay. The organization is created at once but cannot create servers, projects or environments until it is active.
- Approve new customers by hand (second switch): a paid signup waits in Billing → Organizations under the To approve filter (also listed on the Billing Overview) until an Admin or Billing manager approves or rejects it. Approvers get an email. Rejecting needs a reason, voids the open invoice and tells the customer; it does not refund, so refund the payment yourself. Approving a signup that is still awaiting payment opens it without payment.
- With approval off, a signup opens the moment its first invoice is paid. A plan with a trial or a free plan opens at once.
- A signup unpaid after 14 days expires and its invoice is voided. Each person may have one unfinished signup and up to 5 self-service organizations.
- Keep internal plans private. New plans are public by default, so they appear on the Pricing page once self-service is on. Turn off public on any internal, negotiated or legacy plan first.
Access rights
| Action | Super admin | Billing manager | Customer Owner / Admin | Customer Developer / Viewer |
|---|---|---|---|---|
| Manage plans; put organizations on a plan, trial or exempt | Yes | Yes | No | No |
| Create, send and void invoices | Yes | Yes | No | No |
| Record, confirm and reject payments | Yes | Yes | No | No |
| Change billing settings; run billing; check Odoo | Yes | Yes | No | No |
| See their own organization's plan, usage and non-draft invoices | Yes | Yes | Yes | No |
| Pay (card, or submit a reference) | — | — | Yes | No |
| See the banner text | Yes | Yes | Yes | Yes (text only, no link) |
| Anything else under Admin | Yes | No | No | No |
All of this is enforced by the API, not just hidden in the interface. Asking for another organization's invoice answers “not found”.
Limits to know about
- No proration when a plan changes mid-period.
- No automatic refunds; voiding an invoice does not refund it.
- Mobile money is reference-and-confirm; there is no EVC Plus, Zaad or WAAFI integration.
- One currency for the whole platform; changing it affects new invoices only.