Billing Integration
Endpoints in the agent so your billing system can suspend, resume, or rate-limit one of your customers — a tenant — when their invoice changes. It is part of the agent's normal API (REST plus the cenvero-str-ctl CLI); you don't build anything beyond the HTTP calls.
The intended shape is: your billing system already knows who has paid. When that answer changes, it makes one call per affected tenant. Nothing polls, and the agent never talks to your billing system.
How enforcement actually works
Worth understanding before you wire it up, because it determines what "suspended" means for a customer and what you can promise them.
Suspending is a firewall action, not a switch. When you suspend a tenant, the agent looks up every endpoint belonging to that tenant's networks and installs a drop rule for each endpoint's address. Traffic from those addresses stops being forwarded. Resuming removes exactly those rules and nothing else — they are tagged with the tenant's id, so a resume can never disturb a rule you wrote yourself.
Two properties follow, and both matter in practice:
- It is idempotent. Suspending an already-suspended tenant is harmless — an endpoint that already has its drop rule is skipped. Your billing system can retry a failed call, or re-send the current state on a schedule, without special-casing anything.
- Existing connections are cut, not drained. The rule applies to traffic, so a transfer in progress stops. There is no grace period. If you want one, delay the call in your billing system.
Rate-limiting is the bandwidth cap, the same mechanism described in Tenants & Bandwidth. It is a credit allowance that refills at the rate you set: TCP finds the new rate and settles there, UDP over the rate is dropped. Applying a limit to a running tenant takes effect immediately without disturbing established connections.
State is durable and cluster-wide. The tenant's status and cap are persisted, so they survive an agent restart, and in a cluster the change is replicated to the other members. You call one node, not every node.
Suspension holds for endpoints created later. Suspending a tenant that owns nothing yet is fine: there is no address to drop traffic from at that moment, but the suspension is remembered, and any endpoint attached to that tenant afterwards is covered as it is attached. So the order you do things in does not matter — you can suspend an empty tenant, provision it later, and its traffic still does not flow. You do not need to re-send the call.
Get an API key
The operator mints a key on the node; your billing system sends it as a bearer token.
cenvero-str-ctl apikeys mint "billing" # → csk_xxxxxxxxxxxxxxxx (shown once)
cenvero-str-ctl apikeys list
cenvero-str-ctl apikeys revoke <id>
Authorization: Bearer csk_xxxxxxxxxxxxxxxx
The key is shown once, when it is minted — store it then. Mint a separate key for your billing system rather than reusing an operator key, so revoking it cannot lock you out of anything else.
Endpoints
A tenant is addressed by its id. All return JSON.
| Method · Path | What happens |
|---|---|
POST /api/v1/billing/tenants/{id}/suspend | Installs a drop rule per tenant endpoint address. Traffic from the tenant stops. |
POST /api/v1/billing/tenants/{id}/resume | Removes exactly the rules the suspend installed. |
POST /api/v1/billing/tenants/{id}/limit | Caps the tenant's bandwidth. Body: {"rate_mbps": 50}. |
POST /api/v1/billing/tenants/{id}/unlimit | Removes the cap (unlimited). |
GET /api/v1/billing/tenants/{id} | Current state: {id, name, status, max_bandwidth_bps}. |
curl -X POST https://node:7070/api/v1/billing/tenants/t-abc123/suspend \
-H "Authorization: Bearer csk_xxxxxxxxxxxxxxxx"
Unknown tenant → 404.
A worked flow
What a billing system typically does, in order:
# Invoice went unpaid — cut the customer off
POST /api/v1/billing/tenants/t-abc123/suspend
# Confirm what the node now believes
GET /api/v1/billing/tenants/t-abc123
# → {"id":"t-abc123","name":"acme","status":"suspended","max_bandwidth_bps":0}
# Payment arrived — restore them
POST /api/v1/billing/tenants/t-abc123/resume
# Downgraded to a slower plan instead of being cut off
POST /api/v1/billing/tenants/t-abc123/limit {"rate_mbps": 50}
Read back after writing. GET is the node's own view, and it is the answer to "did that actually apply?" — more reliable than inferring it from a 200.
From the CLI
The same actions, for an operator or a script on the node:
cenvero-str-ctl billing suspend <tenant-id>
cenvero-str-ctl billing resume <tenant-id>
cenvero-str-ctl billing limit <tenant-id> --rate-mbps 50
cenvero-str-ctl billing unlimit <tenant-id>
cenvero-str-ctl billing status <tenant-id>
What this is not
- Not invoicing. The agent has no concept of an invoice, a price, or a due date. It enforces what you tell it, and your billing system remains the source of truth.
- Not the customer panel's billing. Orders, invoices and payment in the management panel are a separate thing entirely — see Your account. These endpoints are for your system controlling your customers on your nodes.
- Not a usage meter. For how much a tenant actually transferred, use the accounting and metrics surfaces — see Monitoring & Observability.
See also
- Tenants & Bandwidth — what a tenant is, and how the bandwidth cap behaves.
- Monitoring & Observability — usage figures to bill against.
- API Reference — the full endpoint surface and authentication.