Plans & Entitlements
What this covers / who it's for. Who gets which capability, on what terms, and why a feature can be unavailable even on the top plan: the two-axis "jurisdiction gates, tier entitles" model, the three commercial tiers, the five kinds of feature, today's live catalog, per-tenant overrides, and how each kind of refusal feels to the user.
The model: jurisdiction gates, tier entitles
Whether a tenant can use a feature is decided by two independent axes, in a fixed order:
- The jurisdiction gate (regulatory). Does the tenant's jurisdiction permit this feature at all? If not, the feature is simply not offered — no plan, upgrade, or override can buy it back. Compliance beats commerce.
- The tier entitlement (commercial). If the jurisdiction permits it, the tenant's plan sets the terms: on/off, how many, at what rate.
Everything fails closed: a tenant with no jurisdiction or plan assigned, an unknown
feature, or an inactive jurisdiction gets nothing. Engine specifics:
features README.
The three tiers
| Tier | Positioning |
|---|---|
| Starter | Entry tier |
| Growth | Mid-volume tier |
| Elite | High-volume tier |
Each tenant is assigned one tier (its level) and one jurisdiction. There is no self-service
plan-change surface today — tier assignment is an operational act.
The five kinds of feature
Every feature is one of five types, and the type determines both the entitlement shape and what a refusal means:
| Type | Behavior | When exhausted, the user sees |
|---|---|---|
| Boolean | Simple on/off per tier | FEATURE_UNAVAILABLE (403) — not on your plan / not in your jurisdiction |
| Quota | N units per period; resets (e.g. monthly) | QUOTA_EXCEEDED (429) — transient: retrying after the window resets will work |
| Meter | Pay-per-unit at a flat rate; no cap | Never refused for volume — usage accrues and the rate applies |
| Stepped | Rate bands on cumulative volume — the marginal rate falls as more volume clears | Never refused for volume — the applicable band's rate applies |
| Limit | A hard structural cap that never resets by itself, but is releasable (freeing capacity restores headroom) | LIMIT_REACHED (409) — permanent: retrying is pointless; free capacity or upgrade |
The QUOTA_EXCEEDED (429) vs LIMIT_REACHED (409) split is deliberate product language: a
quota heals itself on the next reset, a limit never does — so clients (and generic
retry-on-429 logic) are told the truth about whether waiting helps.
Today's live catalog
Five real features exist today, one of each type. All magnitudes are placeholder values pending product/pricing input — illustrative, not committed price points (they are marked NOT-FINAL in the catalog source).
| Feature | Type | Starter | Growth | Elite |
|---|---|---|---|---|
Custom team roles (team.advanced-roles) | Boolean | — | — | ✔ |
Team seats (team.seats) | Limit | 3 | 10 | 50 |
Conversion orders per month (payments.monthly-orders) | Quota (monthly) | 100 | 1 000 | 10 000 |
Per-order fee (payments.order-fee) | Meter | 1.00 | 0.50 | 0.25 |
Payout-volume fee (payments.payout-volume-fee) | Stepped | 3 bands | 3 bands | 3 bands |
Product behavior worth knowing behind three of these:
- Seats are checked when a member is invited but consumed when the invitation is accepted — over-issued invites mean the last joiner can be the one refused. Deactivating a member releases their seat. See Personas & access.
- Monthly orders are reserved before the provider call, so a tenant at its quota is refused before any order is created on the rail.
- Payout-volume fee bands apply to cumulative cleared payout value — cancelled or rejected payouts accrue nothing. Example (Elite): first 1 M at rate 0, up to 3 M at 0.001, the remainder at 0.0005 — thresholds are cumulative ceilings, so at exactly 1 M the next unit already prices in the second band.
Both live catalogs currently grant their features in the same jurisdiction set: ZA, NG, KE, GB, US, and the EU bloc (which reaches every EU member automatically — see below).
Jurisdictions — the regulatory axis
The platform carries a full ISO catalog of the world's jurisdictions (~5 308 seeded):
13 supranational blocs (EU, Eurozone, EEA, Schengen, EFTA, GCC, ECOWAS, EAC, SADC, ASEAN,
MERCOSUR, WAEMU, CEMAC), 249 countries, and 5 046 subdivisions (states, provinces,
regions — including nested ones), each with currency and region reference data. Specifics:
jurisdictions README.
What matters for product reasoning:
- Grants are written once, high up, and inherit. A feature permitted "in the EU" reaches every EU member country and all their subdivisions; a grant at country level reaches its subdivisions. Inheritance runs down geography and across bloc membership (Germany is simultaneously in the EU, Eurozone, EEA, and Schengen).
- Inheritance stops at an inactive jurisdiction — fail-closed. Deactivating a country cuts it (and its subdivisions) off from every grant, including inherited ones — a suspended market cannot be re-entered via its bloc membership. An unknown, blank, or inactive jurisdiction permits nothing.
- Non-canonical codes are tolerated (aliases like
UK→GB,EL→GRresolve before gating), so a tenant is never denied on a spelling technicality. - Each tenant is assigned one jurisdiction today (multi-jurisdiction tenants are tracked future work). Which jurisdictions permit which features is declared in code by the feature's owning team and synced into the catalog — there is no ad-hoc editing surface yet.
Per-tenant overrides
A specific tenant can be granted terms different from its tier — an operator action (gated by its own operator permission), not self-service:
- Precedence is override → tier → catalog default — but always under the jurisdiction gate: an override can never grant a jurisdiction-forbidden feature.
- An override can also force a feature off for one tenant, beating a tier that would enable it.
- Overrides can be time-boxed (an expiry after which the tenant falls back to its tier) and revoked at any time. Grants and revocations are recorded as events.
Typical uses: a pilot tenant trying a top-tier capability, a temporary quota bump, or switching a feature off for one tenant during an incident.
How refusals feel to the user (summary)
| Signal | HTTP | Meaning | What the user should do |
|---|---|---|---|
FEATURE_UNAVAILABLE | 403 | Not offered here (jurisdiction) or not on this plan / forced off | Upgrade — unless it's jurisdictional, in which case nothing |
QUOTA_EXCEEDED | 429 | The period's allowance is spent | Wait for the reset (e.g. next month) or upgrade |
LIMIT_REACHED | 409 | A structural cap is full | Free capacity (e.g. deactivate a member) or upgrade |
Refusal messages are written to be actionable and never leak internal feature keys. Usage windows reset both on schedule and lazily on next use, so a rolled-over quota is never stuck stale.