Term Fees
Permission node: BILLING.FEESAPI: /api/v1/billing/term-fees
A term fee is a charge attached to a term — tuition, the general fee, a technology fee. It is the most structurally interesting object in billing, because two independent choices decide how it is assessed.
Two orthogonal axes
These are not one setting with four values. They are two settings, and any combination is valid.
How the amount is computed
| Meaning | |
|---|---|
| Flat | One flat_amount, charged as-is |
| Banded | Amount depends on credits taken, via the fee's bands |
Who it applies to
| Meaning | |
|---|---|
| Universal | Everyone in the term |
| Category-based | Only those matching a category's scope |
A banded universal fee (tuition by credit load for everybody) and a flat category fee (a lab fee for one degree level) are both ordinary.
| Action | Endpoint |
|---|---|
| List | GET /billing/term-fees |
| Get one | GET /billing/term-fees/{termFeeID} |
| Its bands | GET /billing/term-fees/{termFeeID}/bands |
| Its categories | GET /billing/term-fees/{termFeeID}/categories |
| Available rule fields | GET /billing/term-fees/fields |
| Create | POST /billing/term-fees |
| Update | PATCH /billing/term-fees/{termFeeID} |
| Delete | DELETE /billing/term-fees/{termFeeID} |
Bands
A band covers a credit range and carries the amount for it.
max_creditsmay be empty, and empty means no upper bound — that is how the top band ("12 credits and above, full-time rate") is expressed. It is not a missing value.min_inclusiveandmax_inclusivedecide whether a student sitting exactly on a boundary falls in this band or the next. A student at precisely 12 credits is the case to check.
Leave a gap between bands and students landing in it are charged nothing for that fee, with no error raised.
Categories
A category narrows a fee to part of the population using four optional scopes: degree level, student type, campus and student list. Each is independently optional, and leaving one empty means "do not narrow on this axis". Where several categories match, the lowest priority wins.
A category belongs to a fee, not to a term
term_fee_categories.term_fee_id points at the fee. It is a natural mistake to read it as a term, and code that did so returned quietly wrong rows rather than failing.
Before changing a live fee
Charges already posted are not recalculated. Editing a fee changes what future assessments produce, leaving posted charges derived from a definition that no longer exists — which is how a bill becomes unexplainable months later when a student disputes it. For a mid-year change, prefer ending the current fee and creating its successor.