Skip to content

Concepts

Entitlements

An entitlement answers one question: does this user have access to this product right now, and until when? Aroli computes it from a ledger of grants using a small set of exact rules.

The model

Every time a user gains access - by redeeming a license key, or when you grant time from the dashboard or the management API - Aroli appends a grant to an append-only ledger. The entitlement for a product (its status and expiresAt) is recalculated from that ledger, so it is always explainable.

Grant durations offered in the dashboard are 1, 7, 30, 90, 180 or 365 days, any custom number of days, or lifetime (durationDays: null).

The rules

  1. Grants are applied in creation order. The oldest grant is applied first.
  2. Time stacks and never overlaps. A timed grant starts at max(grant time, current expiry). If the user still has time left, the new time is added after it.
  3. After a lapse, time starts fresh. If the entitlement had already expired when the grant was made, the grant starts at the grant time - the expired gap is not back-filled.
  4. Lifetime wins. A lifetime grant makes the entitlement lifetime (expiresAt: null).
  5. Freezing pauses the clock. While frozen, the entitlement is inactive and no time is consumed. Unfreezing pushes the expiry forward by exactly the frozen duration.
  6. Revocation is precise. Revoking a license withdraws only the time that license granted; time from other grants is untouched.

Examples

Stacking

Redeem a 30-day key, then a 90-day key on day 10

Key B's 90 days begin at key A's expiry (day 30), not on day 10. Total access: 120 days.

After a lapse

A 30-day grant expires; 20 days later the user redeems another 30-day key

The second grant starts on the day it's redeemed. The 20 expired days are not refunded or back-filled.

Freezing

Freeze for 14 days in the middle of a 90-day period

While frozen, the user has no access and no time is used. On unfreeze, expiresAt moves 14 days later.

Revocation

Suppose a user redeemed key A (30 days) and key B (90 days), stacked to 120 days. If you revoke key A, the entitlement is recalculated without key A's grant: the user keeps key B's 90 days, measured from when key B was granted under the rules above. Nothing granted by other keys or manual grants is removed.

Lifetime grant

Once a lifetime grant applies, the entitlement no longer expires (unless that grant itself is revoked).

Checking access

In your app, call session.hasEntitlement("pro") (SDK) or GET /api/v1/client/entitlements/pro. The response includes active, status (ACTIVE, FROZEN, EXPIRED, REVOKED or NONE) and expiresAt.

Webhook

Whenever an entitlement changes, Aroli emits an entitlement.changed webhook - useful if your backend mirrors access.