> For the complete documentation index, see [llms.txt](https://docs.layeronecloud.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.layeronecloud.com/platform/billing/statements-and-pools.md).

# Statements, bandwidth pool and tenure rewards

arrived; usage is billed hour by hour against credit, so there is nothing to invoice at month end — there is a period summary of the ledger:

## 4.11 Statements and receipts <a href="#id-411-statements-and-receipts" id="id-411-statements-and-receipts"></a>

**A statement is not an `Invoice`.** Invoices stay receipts for money that arrived; usage is billed hour by hour against credit, so there is nothing to invoice at month end — there is a **period summary of the ledger**:

* opening credit (balance at the first instant of the month);
* credits added (deposits, bonuses, refunds, upward adjustments);
* usage by category (servers, managed services, floating IPs, bandwidth, API, other, downward adjustments);
* usage by resource (the line items);
* a daily chart;
* closing credit (live for the current month, last day for past months).

The current month is **in progress** and openable on any day; past months are **closed**. **Nothing is snapshotted** — the ledger is the source of truth and the document is recomputed on every render, so there is no counter to roll over on the 1st and no month-end job.

Surfaces: client Billing lands on **Statements** (`STMT-YYYY-MM`), with Receipts, Bandwidth (purchase and overage preference) and Payment methods as the other sections of its secondary sidebar. Transfer usage is **Networking → Bandwidth usage** (`/client/billing/bandwidth/`). `/client/billing/statements/<YYYY-MM>/` is the printable document; `/client/billing/receipts/<id>/` is a printable payment receipt for a paid invoice. The admin client record shows this-month usage on its metric strip and lists statements first; `admin-client-statement` is **Support-readable (read-only)**. A leftover `?usage_month=` forwards onto that month's statement.

**The client Billing metric is "Account credit", not "Available credit".** It renders `account_credit_balance`, and `available_account_credit` — what checkout actually enforces — is a different, smaller number: it subtracts what a prepaid monthly or annual term has already committed the balance to funding ([4.3](/platform/billing/model-and-catalog.md#id-43-orders-and-checkout)). Labelled as available, a customer holding a $17.99 annual term read "Available credit $17.99" and was then refused a $5 order by the figure that had already spoken for it. The committed portion is disclosed under the figure whenever there is one. (An organization tenant sees "Tenant contribution" instead, which is its own ledger balance and is labelled as such, because credit pools at the organization.)

Saved payment methods appear only under Billing → Payment methods; adding, defaulting or removing a card returns there. Awaiting-payment orders sit at the **bottom**, outside every tab, because they are not `Invoice` rows.

## 4.12 Bandwidth pool <a href="#id-412-bandwidth-pool" id="id-412-bandwidth-pool"></a>

Transfer is **pooled per account**, never a per-server cap. A plan's published `bandwidth_tb` is a display figure; `bandwidth.account_allowance_tb` is the authority.

```
usable allowance = free base + earned tenure rewards + earned instance credits
                   + active prepaid blocks
```

* **Free base** is 2 TB per UTC calendar month. A per-account base override replaces only that base.
* **Tenure rewards** add 250 GB (0.25 decimal TB) per month from day 90 (Gold) and another 1 TB per month from day 365 (Platinum), in full as soon as the threshold is reached, without a deposit or claim. With the standard base that is 2.25 TB from day 90 and 3.25 TB from day 365. These are separate from the deposit *rates* in [4.13](#id-413-tenure-rewards) and use the same service streak; the Rewards program page lists them on the Gold and Platinum rungs.
* **Instance credits**: every provisioned VPS earns up to 500 GB (0.5 TB) per month, **prorated by elapsed provisioned lifetime**:

  ```
  start   = max(provisioned_at, month_start)
  end     = min(now, deletion_cutoff_if_present, next_month_start)
  earned  = 0.5 TB × elapsed_seconds / seconds_in_this_calendar_month
  ```

  Use the actual number of seconds in the month, including leap-year February — the 730-hour advertised billing equivalent does not apply. **Sum VPS contributions before rounding down to 0.0001 TB**, so the account total does not lose one rounding fraction per VPS. Starting a VPS does not grant its whole monthly credit immediately, and increasing its plan size does not change the rate. Stopped and suspended provisioned instances keep earning while their resources remain allocated. The deletion-request timestamp freezes further accrual; credits already earned remain until the monthly reset. Recreating a destroyed VM archives its prior lifetime before replacing `provisioned_at`, so credits earned earlier in the month survive.
* **Potential** credits = earned + what currently provisioned instances would earn through month end. Potential is an estimate and **is not spendable allowance**. Free and instance credits reset at 00:00 UTC on the 1st and do not carry forward.
* **Purchased blocks** are available immediately and keep their calendar-month pricing and renewal behaviour. An **auto-renewal the pooled balance cannot cover lets the block lapse** rather than charging into a negative balance; see [4.10](/platform/billing/credit-automation.md#id-410-credit-automation-the-000-floor-grace-window-suspension-termination). The reminder `upcoming_charge_reminder_days` ahead says which of the two is coming, because a reminder that quotes a charge and a balance and leaves the customer to compare them only works for the customers who were going to be fine anyway.

Bandwidth credits represent transferable data, **not money in the ledger**. Per-server inbound/outbound figures are usage attribution.

**Overage is live used-minus-pool, not the stored `overage_tb` column** wherever a decision is made: the column only updates when the charger runs, so reading it would hide someone who went over since the last pass and keep someone who bought a covering block in the meantime. Closed-period overage uses credits earned within that period, including instances destroyed before it closed, and a closed period's saved free allowance **retains its tenure rewards** even if the streak later changes. Overage already charged is never refunded by credits earned later; the daily charging high-water mark is authoritative.

When automatic overage billing is off, a bandwidth hold recovers when the month resets, a tenure reward or more instance credits cover usage, a sufficient block is purchased, or the customer enables overage billing.

`/client/billing/bandwidth/` is the dedicated read-only breakdown, reached from the Networking section sidebar as **Bandwidth usage**: the Pool/Usage chart (free, instance, purchased, and still-to-earn credits against transfer already consumed), current UTC month and reset date, usable allowance, usage, remaining, and a source table separating the configured base, each 90-day and 365-day reward, earned instance credits and purchased blocks. Locked rewards show their requirement and days remaining with zero available *and* zero potential. The server table lists eligible service days, earned and potential credits and inbound/outbound/total transfer for every owned VPS with credits or usage in the month, retains destroyed-server contributions, and paginates at 50 with totals covering the whole account on every page. Any account transfer without server attribution is disclosed separately. Four decimal places for TB source totals, two for GB server figures — display rounding can leave small differences between rows and the total.

## 4.13 Tenure rewards <a href="#id-413-tenure-rewards" id="id-413-tenure-rewards"></a>

Two halves of one number. **Tenure** is how long the organization has continuously had at least one billing server. The client area turns it into deposit tiers on **Rewards program** (`/client/rewards/`, `billing_public:client-rewards`); the 90-day and 365-day bandwidth gifts from [4.12](#id-412-bandwidth-pool) are shown on the Gold and Platinum rungs rather than as a second ladder. The console turns tenure into a retention view. Both read `apps/billing/rewards.py` — there is deliberately **no second definition** of "how long has this customer been with us", because the customer's rewards page and the operator's screen quoting different numbers is what makes a loyalty program unarguable-with. Standing is the organization's: every tenant shares one streak, and members open the same page and see the same numbers. Adding credit stays owner-only (`billing_management_required`), the same as Billing and Refer and earn.

| Tier     | Tenure                        | Deposit bonus | Bandwidth            |
| -------- | ----------------------------- | ------------- | -------------------- |
| Silver   | 0 days (everyone starts here) | none          | —                    |
| Gold     | 90 days                       | 5%            | +250 GB/month        |
| Platinum | 365 days                      | 10%           | +1 TB/month, stacked |

Thresholds, rates, labels and chip tone live on `RewardTier` in `REWARD_TIERS`, ordered lowest first; adding a rung is one line. Bandwidth earning still lives on `BANDWIDTH_REWARDS`; `RewardTier.attached_bandwidth_rewards` is display mapping only, so a gift whose day count matches a deposit rung lands on that card, and one that falls between rungs lands on the lower card. The tone lives on the tier rather than in `l1_ui._STATUS_TONES` because a tier is not a model status — but it lives in exactly one place for the same reason status colour does.

**Tenure is a streak.** `account_tenure()` merges every server's `[provisioned_at, destroyed_at)` interval and returns the start of the run that is still open. No open run is zero days and Silver, however long the account has existed. The merge is across the **billing pool** (`credit_pool_members`): every tenant of the same organization, because deposits credit that pool and a second workspace is not a new customer. An unanchored personal account (a member's left-behind history) stays outside it, the same as credit. Four decisions carry the weight:

* **"Active" is the population that bills.** `TENURE_ENDED_VM_STATUSES` is `{DESTROYED, DELETING}` — the same exclusion as `billing_business_metrics` and the metering pass. A stopped or billing-suspended server keeps the clock running because it keeps charging by the hour. A second, friendlier list of "active" statuses here is how the loyalty counter and the invoice end up disagreeing about whether somebody is a customer. Pending, provisioning, staged and failed rows with no `provisioned_at` do not count. A running, stopped or suspended server that never received the stamp still bills, so `created_at` is the start rather than treating it as unprovisioned.
* **A rebuild is not a reset.** `TENURE_REJOIN_GRACE` (24 h) bridges a shorter gap on purpose: destroy-and-redeploy is the single most routine thing a technical customer does, and a strict zero-second rule silently costs them twelve months of standing, discovered at their next deposit.
* **A DESTROYED row with no `destroyed_at` still ends its interval**, falling back to `updated_at`. Treating a missing teardown time as "still running" hands Platinum to an account with nothing left, which is the expensive direction to be wrong in.
* **A new tenant does not restart the clock.** Counting only the selected `BillingAccount` made Rewards, deposit bonuses and the bandwidth tenure gift drop to Silver on a workspace created after the organization work, while the original tenant still held the servers that had been billing for months.

`account_tenure_map()` is the bulk form (one query for a page of accounts).

**The deposit bonus** posts from `record_account_credit_for_paid_invoice` through `services._grant_tenure_reward_bonus`, on the branch that created the credit row — the same once-per-invoice guarantee referral accrual rides, which is why it cannot double up when the webhook and the receipt page race. Four properties:

* **The base is `invoice.total`, not the credit that posted.** One payment writes several ledger rows (the deposit, the LET match, the recovery make-up entry) and only the first is money that arrived; a bonus on promotional credit compounds one giveaway into another.
* **The entry is an `ADJUSTMENT`, never a `CREDIT`.** `unique_credit_ledger_entry_per_invoice` reserves `CREDIT` for the row that *is* the deposit; a second credit row against the same payment reads as the deposit having been banked twice. It carries `metadata["origin_invoice_id"]` instead of an `invoice` FK.
* **Idempotency is asserted, not assumed:** the grant re-checks under a `select_for_update` on the account, because it mints credit and the once-per-call guarantee lives in another module.
* **Silver pays no deposit bonus**, and a zero rate returns before touching the database.

`projected_deposit_bonus` / `deposit_bonus_for` are what the add-credit page quotes, so the page cannot promise a figure the ledger will not post. Failures are logged and swallowed: a bonus that cannot be written must not turn a payment that already cleared into a 500.

**No new tables.** The tier is derived on read and the bonus is an `AccountLedgerEntry` like every other movement of credit.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.layeronecloud.com/platform/billing/statements-and-pools.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
