Herald

Points Quotas (Rolling Windows)

Configure rolling-window quotas for subscription and free-periodic credits. A single entitlement can carry multiple windows like {5h: 500, week: 5000, month: 20000}; the available quota at any moment is the minimum remaining across all windows.

Configure rolling-window quotas for subscription and free-periodic credits. A single entitlement can carry multiple windows, e.g. {5h: 500, week: 5000, month: 20000}. At any moment the available quota is the minimum of "limit − used-in-window" across all windows. If the 5-hour window is exhausted, the current available quota is 0 even if the weekly/monthly windows still have room.

This applies to subscription_credit (credits granted with a subscription) and free_periodic_credit (free credits granted per period). Top-up, registration, and granted credits are pool balances — they are not affected by window quotas.

Who this is for

Realm Admins who configure subscription quotas and the free-period quota for new users. The configuration happens in the admin console or via API.

Core idea

A quota window has two fields: a length in seconds and a limit. The window is rolling — it looks back windowSeconds from now and sums what was consumed. At least one window, at most eight. The user's available quota is the minimum remaining across all configured windows, so the tightest window is the one that bites.

Configure subscription quotas

Subscription quotas hang off the Entitlement Mapping. Configure them on the Entitlement Mappings page or via PUT /api/bill/{realmId}/entitlement-mappings/batch.

Admin console

  1. Log in as Realm Admin and go to /{realmId}/manage/billing/entitlement-mappings
  2. Pick the target product from the product list
  3. Find the multi-window quota editor in the advanced config of the price row
  4. Add window rows and save

API request example

PUT /api/bill/{realmId}/entitlement-mappings/batch
{
  "paymentProvider": "stripe",
  "externalProductId": "prod_xxx",
  "updates": [
    {
      "mappingId": "550e8400-e29b-41d4-a716-446655440000",
      "entitlementKey": "pro-plan",
      "billingType": "recurring",
      "billingPeriod": "month",
      "pointsPerPeriod": 1000,
      "grantPeriodType": "monthly",
      "validityDays": 30,
      "grantOnSubscribe": true,
      "maxPeriods": 10,
      "enabled": true,
      "quotaWindows": [
        { "windowSeconds": 18000, "limit": 500 },
        { "windowSeconds": 604800, "limit": 5000 },
        { "windowSeconds": 2592000, "limit": 20000 }
      ]
    }
  ]
}

Field constraints:

FieldConstraintDescription
windowSecondsGreater than 0Sliding window length, in seconds
limitGreater than or equal to 0Quota cap for this window
quotaWindowsAt most 8 rowsExceeding this is rejected with 400

The configuration only affects subsequently granted quota entitlements; already-active entitlements keep the quota_windows snapshot they were granted with.

Active-subscription protection

If a batch update would flip a mapping that still has active subscriptions from enabled=true to enabled=false, the backend rolls back the whole transaction and returns 409; the response body includes the count of affected active subscriptions. The frontend surfaces this with a confirm dialog.

Configure the Realm default free-period quota

The periodic quota a free user gets at registration is controlled by the Realm default config, at /{realmId}/manage/points/default-config, backed by GET/PUT /api/points/{realmId}/default-config.

Admin console

  1. Log in as Realm Admin and go to /{realmId}/manage/points/default-config
  2. Find the free-period multi-window quota editor
  3. Add window rows and save

API request example

PUT /api/points/{realmId}/default-config
{
  "registrationBonusPoints": 1000,
  "freePeriodicPointsAmount": 50,
  "freePeriodicGrantPeriodType": "daily",
  "freePeriodicValidityDays": 1,
  "freePeriodicQuotaWindows": [
    { "windowSeconds": 86400, "limit": 50 },
    { "windowSeconds": 604800, "limit": 200 }
  ]
}

freePeriodicQuotaWindows semantics:

  • null: leave the stored value untouched (PUT is a partial update)
  • []: clear the window configuration
  • [{windowSeconds, limit}]: replace with the new window definitions

Validation matches the Entitlement Mapping rules: windowSeconds greater than 0, limit greater than or equal to 0, at most 8 rows.

Registration bonus credits

registrationBonusPoints controls the one-time registration_credit a new user gets at registration, which is permanent. This field sits in its own area of the same config page as the free-period quota.

Verify the configuration took effect

  1. After a new user registers or a new subscription is paid, visit /{realmId}/user/points
  2. The usage dashboard on the page shows, per window row, the remaining / limit / used / recovery time
  3. If no window rows appear, check whether the corresponding mapping or Realm default has quotaWindows configured, and whether the user has actually been granted the quota entitlement

How consumption mixes with pool balance

On consume, the window quota is deducted first within the same transaction; any overflow is taken from the top-up / registration / granted pools. If the combined total is insufficient, the whole consume rolls back and is rejected — no partial deduction. See Billing Architecture for the credit-account and pool model.

On this page